Пятница, голова уже не варит, максимум на что ее еще хватит написать ответ на очередной вопрос на форумах MSDN. Суть вопроса: нужно при выборе элемента в дереве не подсвечивать стандартное выделение всего TreeViewItem, а подсвечивать часть DataTemplate, который отвечает за показ элементов дерева. Т.е. сделать надо, чтобы выделение работало вот так, как на январе:
Интересно? Тогда идем под кат.
Первое с чего начнем, это с модели данных. Я особо усердствовать не буду и воспользуюсь, благо всего неделя до нового года, вот таким классом:
Добавляем в дерево загрузку данных:
Подключаем этот конвертер в ресурсы окна:
Интересно? Тогда идем под кат.
Первое с чего начнем, это с модели данных. Я особо усердствовать не буду и воспользуюсь, благо всего неделя до нового года, вот таким классом:
public class Model : DependencyObject { public bool IsSelected { get { return (bool)GetValue(IsSelectedProperty); } set { SetValue(IsSelectedProperty, value); } } // Using a DependencyProperty as the backing store for IsSelected. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(Model), new PropertyMetadata(false)); public string Name { get; set; } public Model[] Children { get; set; } public static Model[] DemoData { get { var result = new Model[1]; result[0] = new Model() { Name = "Зима" }; result[0].Children = new[] { new Model() { Name = "Декабрь" }, new Model() { Name = "Январь" }, new Model() { Name = "Февраль" } }; return result; } } }Теперь переходим к разметке.
Добавляем в дерево загрузку данных:
<TreeView ItemsSource="{Binding Source={x:Static local:Model.DemoData}}">Теперь убираем подсветку выбранной ячейки. Для этого меняем цвет фона выбранного элемента и цвет текста выбранного элемента:
<TreeView.Resources> <Style TargetType="TreeViewItem"> <Style.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/> </Style.Resources> <Setter Property="IsSelected" Value="{Binding IsSelected}" /> </Style> </TreeView.Resources>Теперь, чтобы не заморачиваться с DataTriger-ами добавим простенький конвертер:
public class IsSelectedToBrushConverter : IValueConverter { static Brush HighlightBrush = new SolidColorBrush(Colors.LightBlue); public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Brush result = null; if (value is bool && (bool)value) { result = HighlightBrush; } return result; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Подключаем этот конвертер в ресурсы окна:
<Window.Resources> <local:IsSelectedToBrushConverter x:Key="IsSelectedToBrushConverter" /> </Window.Resources>Все, осталось сделать HierarchicalDataTemplate, в котором будет подсвечивать только то, что нам нужно:
<HierarchicalDataTemplate ItemsSource="{Binding Children}"> <StackPanel Orientation="Horizontal"> <Image Source="Images/snowflake.PNG" Width="20" /> <TextBlock Text="{Binding Name}" Background="{Binding IsSelected,Converter={StaticResource IsSelectedToBrushConverter}}" /> <Image Source="Images/snowflake.PNG" Width="20" /> </StackPanel> </HierarchicalDataTemplate>Как все это выглядит, можно посмотреть в картинке из заголовка поста.
Я вообще отказался от TreeView, вместо этого, сделал своё представление коллекции в итоге в любом контроле унаследованном от ItemsControl'а можно интегрировать дерево, при этом есть поддержка MultiSelect'а, адекватная вертикальная виртуализация, возможность использовать дерево в ComboBox'е, DataGrid'е без особых заморочек.
ОтветитьУдалитьПри этом мне не надо тащить в элементы дерева свойства IsSelected и IsExpanded, так как всё это делается на уровне обёртки в представлении коллекции.
+ имхо, реализовывать в шаблоне выделение не очень по MVVM, по идее, цвет выделения лучше менять в шаблоне контрола, а содержимое этого шаблона можно разбить на части (как вариант).
Так как выделение (CurrentItem) не обязательно IsSelected.
за CurrentItem отвечает представление коллекции (если работает синхронизация), а за IsSelected всего лишь свойство зависимости элемента дерева. + при виртуализации элементы которые находятся за ViewPort'ом не связываны с моделью представления.