您不应该对项目容器进行操作,而是对项目进行操作。
为此,您需要向IsSelected
模型添加一个属性。您还需要选择节点的子项。
为了在 上注册 aMouseBinding
你TreeViewItem
必须覆盖默认ControlTemplate
的TreeViewItem
. MouseBinding
定义在" CTRL + LeftClick"MouseGesture
上触发。向注册的A通过切换属性来执行项目的实际选择。ICommand
MouseBinding
IsSelected
要获取所选项目,您只需遍历源集合(遍历树结构)以收集IsSelected
equals的所有项目true
。
树项.cs
public class TreeItem : INotifyPropertyChanged
{
public TreeItem(string value)
{
this.Value = value;
this.Children = new ObservableCollection<TreeItem>();
}
private void SelectAllChildren(IEnumerable<TreeItem> children, bool isSelected)
{
foreach (TreeItem child in children)
{
child.IsSelected = isSelected;
SelectAllChildren(child.Children, isSelected);
}
}
public string Value { get; set; }
public ObservableCollection<TreeItem> Children { get; set; }
// Toggle IsSelected
public ICommand SelectItemCommand => new RelayCommand(param => this.IsSelected ^= true);
private bool isSelected;
public bool IsSelected
{
get => this.isSelected;
set
{
this.isSelected = value;
OnPropertyChanged();
SelectAllChildren(this.Children, this.IsSelected);
}
}
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion Implementation of INotifyPropertyChanged
}
视图模型.cs
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
this.TreeItems = new ObservableCollection<TreeItem>();
}
private IEnumerable<TreeItem> GetSelectedItems(IEnumerable<TreeItem> items)
{
List<TreeItem> selectedItems = new List<TreeItem>();
foreach (TreeItem item in items)
{
if (item.IsSelected)
{
selectedItems.Add(item);
}
else // Check if unselected node has selected child nodes
{
var selectedChildItems = GetSelectedItems(item.Children);
selectedItems.AddRange(selectedChildItems);
}
}
return selectedItems;
}
public ObservableCollection<TreeItem> TreeItems { get; set; }
}
主窗口.xaml
<Window>
<Window.Resources>
<ViewModel />
</Window.Resources>
<TreeView ItemsSource="{Binding TreeItems}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type TreeItem}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Value}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel>
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="Expander"
IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
Background="Transparent"
BorderThickness="0"
RenderTransformOrigin="0.5, 0.5">
<ToggleButton.RenderTransform>
<RotateTransform />
</ToggleButton.RenderTransform>
<ToggleButton.Content>
<TextBlock Text=""
FontFamily="Segoe MDL2 Assets" />
</ToggleButton.Content>
</ToggleButton>
<Border x:Name="SelectionBorder">
<ContentPresenter x:Name="PART_Header"
Content="{TemplateBinding Header}">
<!-- Register to handle CTRL+LeftClick gesture -->
<ContentPresenter.InputBindings>
<MouseBinding Command="{Binding SelectItemCommand}">
<MouseBinding.Gesture>
<MouseGesture Modifiers="Control"
MouseAction="LeftClick" />
</MouseBinding.Gesture>
</MouseBinding>
</ContentPresenter.InputBindings>
</ContentPresenter>
</Border>
</StackPanel>
<ItemsPresenter x:Name="ItemsHost"
Visibility="Collapsed"
Margin="12,0,0,0" />
</StackPanel>
<!-- Animate the node's expander -->
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ExpansionStates">
<VisualState x:Name="Expanded">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Expander"
Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
To="90"
Duration="0:0:0.1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsHost"
Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0:0:0"
Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter TargetName="Expander"
Property="Visibility"
Value="Collapsed" />
</Trigger>
<!-- Handle item selection visuals -->
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter TargetName="SelectionBorder"
Property="Background"
Value="DodgerBlue" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Window>