WPF: Setting a binding for all TreeViewItem instance
Greetings,
I'm using WPF with a Model-View-ViewModel pattern, and I have a view model with an IsSelected
property which I want to bind to a TreeViewItem
's IsSelected
property for all TreeViewItem
s in the scope. I'm attempting to do this with a Style
and a Setter
. This works apparently for the root-level TreeViewItem
s, but not for their children. Why is this? How can I have this apply to all TreeViewItem
controls?
Here is the view XAML:
<UserControl x:Class="MyApp.AllAreasView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:MyApp="clr-namespace:MyApp"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="700">
<UserControl.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
<MyApp:CountVisibilityConverter x:Key="CountVisibilityConverter" />
<开发者_如何学运维;HierarchicalDataTemplate x:Key="AreaTemplate"
DataType="AreaViewModel"
ItemsSource="{Binding Path=SubareasCollectionView}">
<WrapPanel>
<TextBlock Text="{Binding Path=Name}" Margin="0 0 8 0" />
<TextBlock DataContext="{Binding Path=Subareas}"
Text="{Binding Path=Count, StringFormat= (\{0\})}"
Visibility="{Binding Path=Count, Converter={StaticResource CountVisibilityConverter}}" />
</WrapPanel>
</HierarchicalDataTemplate>
</UserControl.Resources>
<TreeView ItemsSource="{Binding TopLevelAreas}"
ItemTemplate="{StaticResource AreaTemplate}">
</TreeView>
</UserControl>
I think we'll need more info to answer your question. Specifically, what your view model(s) look like. Below is an example you can copy and paste that works fine.
Window1.xaml:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Background" Value="{Binding Background}"/>
</Style>
<HierarchicalDataTemplate x:Key="ItemTemplate" DataType="local:DataItem" ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView ItemsSource="{Binding}" ItemTemplate="{StaticResource ItemTemplate}"/>
</Window>
Window1.xaml.cs:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
var dis = new ObservableCollection<DataItem>();
var di = new DataItem() { Name = "Top", Background = Brushes.Red };
di.Children.Add(new DataItem() { Name = "Second", Background = Brushes.Blue });
dis.Add(di);
DataContext = dis;
}
}
public class DataItem
{
public DataItem()
{
Children = new ObservableCollection<DataItem>();
}
public string Name
{
get;
set;
}
public ICollection<DataItem> Children
{
get;
set;
}
public Brush Background
{
get;
set;
}
}
}
working with view models you will get very friendly with the ItemContainerStyle property. what you were doing in your code set the data template for the root level. what you want to do is style each of the items in the treeview, which you can do like so.
<TreeView ItemsSource="{Binding TopLevelAreas}"
ItemContainerStyle="{StaticResource AreaTemplate}">
</TreeView>
enjoy
You have to use as mentioned below. Make use of BasedOn option
<TreeView ItemsSource="{Binding TopLevelAreas}">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource StyleKey}"/>
</TreeView.Resources>
</TreeView>
精彩评论