none
Программно не подключается Style; RRS feed

  • Вопрос

  • private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
            {
                var dtSchemaColor = (DataTable)ColorSchema.Value;
                var bc = new BrushConverter();
                Color Background = Colors.Gainsboro;
                for (var i = 0; i < dtSchemaColor.Rows.Count; ++i)
                {
                    if (Convert.ToBoolean(dtSchemaColor.Rows[i][4]))
                    {
                        Background = (Color) ColorConverter.ConvertFromString(dtSchemaColor.Rows[i][3].ToString());
                    }
                }
                m_lstHitList.Clear();
                
                if (e.ChangedButton == MouseButton.Left) _mouseDown = false;
                
                if (_position.X == 0 && _position.Y == 0) /*если простой щелчок мышью без выделения*/
                    _rect = new Rect(new Point(_initialPoint.X, _initialPoint.Y), new Size(1, 1));
    
               
                
                var m_egHitArea = new RectangleGeometry(_rect);
    
                
                VisualTreeHelper.HitTest(MyDataGrid, null, HitTestCallback, new GeometryHitTestParameters(m_egHitArea));
    
                MyCanvas.Children.Remove(_current);
    
                foreach (var border in m_lstHitList)
                {
                     border.Background = new SolidColorBrush(Background);
                    //border.Style = (Style)FindResource("FineMesh");
                   
                }
            }

    <LinearGradientBrush EndPoint="1,1" StartPoint="0,0" x:Key="Gradient">
               <GradientStop Color="Transparent"/>
               <GradientStop Color="#77FFFFFF" Offset="0.05"/>
               <GradientStop Color="#77000000" Offset="0.1"/>
               <GradientStop Color="#77FFFFFF" Offset="0.15"/>
               <GradientStop Color="#77000000" Offset="0.2"/>
               <GradientStop Color="#77FFFFFF" Offset="0.25"/>
               <GradientStop Color="#77000000" Offset="0.3"/>
               <GradientStop Color="#77FFFFFF" Offset="0.35"/>
               <GradientStop Color="#77000000" Offset="0.4"/>
               <GradientStop Color="#77FFFFFF" Offset="0.45"/>
               <GradientStop Color="#77000000" Offset="0.5"/>
               <GradientStop Color="#77FFFFFF" Offset="0.55"/>
               <GradientStop Color="#77000000" Offset="0.6"/>
               <GradientStop Color="#77FFFFFF" Offset="0.65"/>
               <GradientStop Color="#77000000" Offset="0.7"/>
               <GradientStop Color="#77FFFFFF" Offset="0.75"/>
               <GradientStop Color="#77000000" Offset="0.8"/>
               <GradientStop Color="#77FFFFFF" Offset="0.85"/>
               <GradientStop Color="#77000000" Offset="0.9"/>
               <GradientStop Color="#77FFFFFF" Offset="0.95"/>
           </LinearGradientBrush>
    
            <Style TargetType="Border" x:Key="FineMesh">
                <Setter Property="Background" Value="{StaticResource Gradient}"></Setter>
            </Style>

    Мышью выделяются контролы, типа Border, через VisualTreeHelper.HitTest загружаются вm_lstHitList. Через Background цвет устанавливается, но если хочу подключить Style - ничего не выходит, стиль не устанавливается, точнее, не меняется.

    Подскажите что не так?

    21 марта 2013 г. 13:03

Ответы

  • Такая же ситуация в social.msdn.microsoft.com/Forums/en-US/wpf/thread/005dad03-c8eb-405f-9567-50653a0e612c

    Можно отлавливать через HitTestFilterBehavior, но приходится пробегать всё дерево пересекаемых объектов и ловить свoй Label.

    Добавил HitTestFilterBehavior и проблема решена

    public HitTestFilterBehavior MyHitTestFilter(DependencyObject htFilter)
            {
                if (htFilter.GetType() == typeof(Label))
                {
                    m_lstHitList.Add((Label)htFilter);
                }
                return HitTestFilterBehavior.Continue;
            }

    и соответственно добавив MyHitTestFilter вместо null:

    VisualTreeHelper.HitTest(MyDataGrid, MyHitTestFilter, HitTestCallback, new GeometryHitTestParameters(m_egHitArea));
    

    и заменив private List<Border> m_lstHitList = new List<Border>(); на List<Label> m_lstHitList = new List<Label>();
    После этого без проблем и стили из ресурса и бэкграунды отрисовываются у Label.

    Тему можно считать закрытой.

    • Помечено в качестве ответа LXGDARKEditor 22 марта 2013 г. 14:23
    22 марта 2013 г. 14:22

Все ответы

  • В дополнение: программно строится таблица Grid, ячейки заполняются Label со своим стилем. НО! VisualTreeHelper.HitTest "ловит" почему то Border, которые программно не подключались. 

    21 марта 2013 г. 14:02
  • Свойства установленные непосредственно перекрывают свойства из стиля. Что бы Bacground из стиля применялся это свойство нужно очистить у Border (через ClearValue) или не устанавливать вообще.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    21 марта 2013 г. 14:03
    Отвечающий
  • В том -то и дело, что Background у бордера не установлен вообще.
    Необходимо подключить либо цвет, либо стиль (в зависимости от условий). Цвет так же зависит от условий, ну и т.д.
    • Изменено rz3rr 21 марта 2013 г. 14:10
    21 марта 2013 г. 14:08
  • В том -то и дело, что Background у бордера не установлен вообще.

    А это что:

    border.Background = new SolidColorBrush(Background);

    ?


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    21 марта 2013 г. 14:08
    Отвечающий
  • я подключаю либо border.Background = new SolidColorBrush(Background); либо border.Style = (Style)FindResource("FineMesh"); Код ещё не закончен. Так вот, при закоментированной строке border.Background = new SolidColorBrush(Background); и раскоментированной border.Style = (Style)FindResource("FineMesh"); цвет не устанавливается.
    21 марта 2013 г. 14:14
  • я подключаю либо border.Background = new SolidColorBrush(Background); либо border.Style = (Style)FindResource("FineMesh"); Код ещё не закончен. Так вот, при закоментированной строке border.Background = new SolidColorBrush(Background); и раскоментированной border.Style = (Style)FindResource("FineMesh"); цвет не устанавливается.

    Все равно попробуйте перед установкой Style сделат:

    border.ClearValue(BackgroundProperty)


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    21 марта 2013 г. 14:15
    Отвечающий
  • border.ClearValue(BackgroundProperty) - не помогло (
    21 марта 2013 г. 14:35
  • border.ClearValue(BackgroundProperty) - не помогло (
    Ну проблема не в установке Style через код. У меня все работает в новом проекте. Мне трудно понять что вы там делаете, я не знаю C#, но явно дело в этих манипуляциях.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    21 марта 2013 г. 14:38
    Отвечающий
  • Когда отдельно моделирую - все нормально работает (без программного построения, всё ручками и без VisualTreeHelper.HitTest ).

    Есть подозрения - не отлавливает ли VisualTreeHelper.HitTest Border из-нутри Label ? Ведь я же Border сам неспосредственно не устанавливаю....

    21 марта 2013 г. 15:03
  • Так оно и есть. Построил отдельный пример. Если Label пустой  - VisualTreeHelper.HitTest "ловит" Border, если добавляю цифру/букву - "ловит" Border и TextBox. Возниакет вопрос - а где же Label?

    Вот Grid Xaml`а

    <Window x:Class="TesT.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <Style TargetType="Label" >
                <Setter Property="HorizontalAlignment" Value="Stretch"/>
                <Setter Property="FontSize" Value="14" />
                <Setter Property="FontFamily" Value="Currier"/>
                <Setter Property="Padding" Value="1"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="BorderBrush" Value="#BB8E8E"/>
                <Setter Property="Margin" Value="-1,0,0,-1"/>
                <Setter Property="HorizontalContentAlignment" Value="Center" />
                <Setter Property="HorizontalAlignment" Value="Stretch"/>
                <Setter Property="VerticalAlignment" Value="Stretch" />
                <Setter Property="VerticalContentAlignment" Value="Center" />
            </Style>
        </Window.Resources>
        <Grid Name="MyDataGrid">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Label Grid.Column="0" Grid.Row="0">1</Label>
            <Label Grid.Column="1" Grid.Row="0">2</Label>
            <Label Grid.Column="2" Grid.Row="0">3</Label>
            .............................................
            <Label Grid.Column="7" Grid.Row="9"></Label>
            <Label Grid.Column="8" Grid.Row="9"></Label>
            <Label Grid.Column="9" Grid.Row="9"></Label>          
            </Grid>
            <Canvas Grid.ColumnSpan="10" Grid.RowSpan="9" Name="MyCanvas" Background="Transparent" IsHitTestVisible="True" MouseDown="Canvas_MouseDown" MouseMove="Canvas_MouseMove" MouseUp="Canvas_MouseUp"/>
        </Grid>
    </Window>
    

    Код С#

    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Shapes;
    
    namespace TesT
    {
        public partial class MainWindow : Window
        {
    
            private bool _mouseDown = false;
            private Rectangle _current;
            private Point _initialPoint;
            private Point _position;
            private Rect _rect;
            private List<Border> m_lstHitList = new List<Border>();
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
    
            private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
            {
    
                MyCanvas.Children.Remove(_current);
    
                foreach (var border in m_lstHitList)
                    border.Background = new SolidColorBrush(Colors.Transparent);
    
                MyCanvas.Children.Remove(_current);
                m_lstHitList.Clear();
    
                _mouseDown = (e.ButtonState == MouseButtonState.Pressed)
                                             && (e.ChangedButton == MouseButton.Left);
                if (!_mouseDown) return;
                var myBrush = new SolidColorBrush(Colors.Green);
    
                _current = new Rectangle();
                _initialPoint = _position = e.MouseDevice.GetPosition(MyCanvas);
                _current.Fill = new SolidColorBrush(Colors.White);
                _current.Opacity = 0.5;
                _current.Stroke = myBrush;
                _current.StrokeThickness = 1;
    
                MyCanvas.Children.Add(_current);
    
                _position.X = _position.Y = 0;
    
            }
    
    
            private void Canvas_MouseMove(object sender, MouseEventArgs e)
            {
                if (!_mouseDown)
                    return;
    
                _position = e.MouseDevice.GetPosition(MyCanvas);
                _current.SetValue(Canvas.LeftProperty, Math.Min(_position.X, _initialPoint.X));
                _current.SetValue(Canvas.TopProperty, Math.Min(_position.Y, _initialPoint.Y));
                _current.Width = Math.Abs(_position.X - _initialPoint.X);
                _current.Height = Math.Abs(_position.Y - _initialPoint.Y);
    
                _rect = new Rect(new Point(Math.Min(_position.X, _initialPoint.X), Math.Min(_position.Y, _initialPoint.Y)), new Size(_current.Width, _current.Height));
            }
    
    
            private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
            {
    
                var bc = new BrushConverter();
                Color Background = Colors.Gainsboro;
    
                m_lstHitList.Clear();
    
                if (e.ChangedButton == MouseButton.Left) _mouseDown = false;
    
                if (_position.X == 0 && _position.Y == 0) /*если простой щелчок мышью без выделения*/
                    _rect = new Rect(new Point(_initialPoint.X, _initialPoint.Y), new Size(1, 1));
    
    
    
                var m_egHitArea = new RectangleGeometry(_rect);
    
    
                VisualTreeHelper.HitTest(MyDataGrid, null, HitTestCallback, new GeometryHitTestParameters(m_egHitArea));
    
                MyCanvas.Children.Remove(_current);
    
                foreach (var border in m_lstHitList)
                {
                    border.Background = new SolidColorBrush(Background);
                }
            }
    
    
    
    
            public HitTestResultBehavior HitTestCallback(HitTestResult htrResult)
            {
                IntersectionDetail idDetail = ((GeometryHitTestResult)htrResult).IntersectionDetail;
    
                switch (idDetail)
                {
                    case IntersectionDetail.FullyContains:
                         MessageBox.Show(htrResult.VisualHit.GetType().ToString());
                        if (htrResult.VisualHit.GetType() == typeof(Border))
                            m_lstHitList.Add((Border)htrResult.VisualHit);
                        return HitTestResultBehavior.Continue;
                    case IntersectionDetail.Intersects: /*частично пересеченные (для обводки и обводимого)*/
                        MessageBox.Show(htrResult.VisualHit.GetType().ToString());
                        if (htrResult.VisualHit.GetType() == typeof(Border))
                            m_lstHitList.Add((Border)htrResult.VisualHit);
                        return HitTestResultBehavior.Continue;
                    case IntersectionDetail.FullyInside: /*полностью пересеченные (попадают внутрь фигуры)*/
                        MessageBox.Show(htrResult.VisualHit.GetType().ToString());
                        if (htrResult.VisualHit.GetType() == typeof(Border))
                            m_lstHitList.Add((Border)htrResult.VisualHit);
                        return HitTestResultBehavior.Continue;
                    default:
                        return HitTestResultBehavior.Stop;
                }
            }
    
        }
    }
    

    Это тестовый пример выделения типа прямоугольного "Lasso"  ячеек таблицы, точнее, содержимого ячеек.
    22 марта 2013 г. 7:48
  • Т.е., напосредственно цвет background`а установить могу, подключить стиль невозможно из-за того, что Border является внутренним контролом Label`а?

    Но по ссылке на выделенный Border я не могу получить Parent, что бы сослаться на Label и повесить на него стиль (проверял). Что можно предринять в такой ситуации?

    22 марта 2013 г. 8:02
  • А вы можете код вашего примера выше описать словами. То есть задача ясна, но я по C# коду не могу понять конкретной реализации. В частности почему такой упор делается на HitTest? Так же не понятно строение макета. Почему Border оказывается внутри Label?

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    22 марта 2013 г. 10:37
    Отвечающий
  • Это весь тестовый макет, полностью работоспособный отдельно. Можно в VS скомпилить (в последнем сообщении). Сделал отдельно от приложения для теста. HitTest находит перерытие объектов - нарисованного мышью на Canvas MyCanvas прямоугольника и Grid MyDataGrid. Другого способа выделения ячеек таблицы мышью не нашел, если не считать кликов по отдельно взятой ячейке (выделять не удобно).

    22 марта 2013 г. 11:52
  • В коде описаны события мышью - Canvas_MouseDown начальная точка рисования прямоугольника, Canvas_MouseMove "тащим" мышью за угол прямоугольника, он отрисовывается с увеличением высоты и ширины. Canvas_MouseUp конечная точка прямоугоьника, вызов VisualTreeHelper.HitTest для определения перекрытия объектов, т.е. какие контролы "накрыл" прямоугольник. Далее устанавливается Background этих контролов и удаляется прямоугольник. HitTestCallback как раз собирает перекрытые контролы. MessageBox.Show (для проверки) сообщает данные о найденных контролах. Label не находит, зато находит внутренние контролы Label. Border нигде самостоятельно ни в коде ни в ксамл не устанавливаю.

    В XAML здесь не стал отображать все лэйблы чтобы не заграмождать код, они однотипны.

    • Изменено rz3rr 22 марта 2013 г. 12:05
    22 марта 2013 г. 12:02
  • Такая же ситуация в social.msdn.microsoft.com/Forums/en-US/wpf/thread/005dad03-c8eb-405f-9567-50653a0e612c

    Можно отлавливать через HitTestFilterBehavior, но приходится пробегать всё дерево пересекаемых объектов и ловить свoй Label.

    Добавил HitTestFilterBehavior и проблема решена

    public HitTestFilterBehavior MyHitTestFilter(DependencyObject htFilter)
            {
                if (htFilter.GetType() == typeof(Label))
                {
                    m_lstHitList.Add((Label)htFilter);
                }
                return HitTestFilterBehavior.Continue;
            }

    и соответственно добавив MyHitTestFilter вместо null:

    VisualTreeHelper.HitTest(MyDataGrid, MyHitTestFilter, HitTestCallback, new GeometryHitTestParameters(m_egHitArea));
    

    и заменив private List<Border> m_lstHitList = new List<Border>(); на List<Label> m_lstHitList = new List<Label>();
    После этого без проблем и стили из ресурса и бэкграунды отрисовываются у Label.

    Тему можно считать закрытой.

    • Помечено в качестве ответа LXGDARKEditor 22 марта 2013 г. 14:23
    22 марта 2013 г. 14:22
  • Спасибо, что поделились решением!

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    22 марта 2013 г. 14:23
    Отвечающий