如何使用wpf中的复选框开发树视图?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用wpf中的复选框开发树视图?相关的知识,希望对你有一定的参考价值。
我有一个要求,我需要动态地向TreeView
添加节点,并使用CheckBox
es添加节点。如果选择了一个CheckBox
,也选择了孩子。
主要是我想动态地向TreeView
添加数据。
一旦你知道如何,这非常简单。
为树视图项数据创建一个视图模型类(我在这里称之为CheckableItem
)。它需要这三件事:
- 它必须实现INotifyPropertyChanged。
- 它需要
Children
类型的ObservableCollection<CheckableItem>
属性。 - 它需要
IsChecked
类型的Visibility
属性,在其setter中,提升PropertyChanged
并且还遍历Children
中的项目并设置它们的IsChecked
属性。
在这个类中实现其他属性以将项的数据暴露给绑定(我的示例假设有一个名为Value
的东西)。或者你可以实现一个类型为Item
的object
类,并在模板中使用ContentPresenter
,但我会留意你。
现在为你的类创建一个HierarchicalDataTemplate
,看起来像这样:
<HierarchicalDataTemplate
DataType="{x:Type local:CheckableItem}"
ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked}"/>
<TextBlock Text="{Binding Value}"/>
</StackPanel>
</HierarchicalDataTemplate>
...和使用它的TreeView
(我假设你已经填充了这些对象的集合,当然):
<TreeView ItemsSource="{Binding MyCollectionOfCheckableItems}"/>
它是如何工作的:TreeView
使用HierarchicalDataTemplate
渲染其ItemsSource
中的每个项目。 HierarchicalDataTemplate
是一个创建HeaderedItemsControl
(在这种情况下是TreeViewItem
)的模板,使用其模板渲染标题,然后使用其ItemsSource
作为控件项目的来源 - 由于它们都是CheckableItem
s,因此被转换为TreeViewItem
的HierarchicalDataTemplate
s。在那之后,它一直是乌龟。
This非常好地概述了TreeView
在实践中是如何运作的,尽管我发现的大多数例子都有很多花里胡哨,但很难看出基本原理有多么简单。如果你了解MVVM,那么前一段是你需要知道的90%。
看一下这个:
DataModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApplication102
{
public class Family : DependencyObject
{
public string Name { get; set; }
public List<Person> Members { get; set; }
}
public class Person : DependencyObject
{
public string Name { get; set; }
}
}
ItemHelper.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApplication102
{
public class ItemHelper : DependencyObject
{
public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.RegisterAttached("IsChecked", typeof(bool?), typeof(ItemHelper), new PropertyMetadata(false, new PropertyChangedCallback(OnIsCheckedPropertyChanged)));
private static void OnIsCheckedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Family && ((bool?)e.NewValue).HasValue)
foreach (Person p in (d as Family).Members)
ItemHelper.SetIsChecked(p, (bool?)e.NewValue);
if (d is Person)
{
int checked = ((d as Person).GetValue(ItemHelper.ParentProperty) as Family).Members.Where(x => ItemHelper.GetIsChecked(x) == true).Count();
int unchecked = ((d as Person).GetValue(ItemHelper.ParentProperty) as Family).Members.Where(x => ItemHelper.GetIsChecked(x) == false).Count();
if (unchecked > 0 && checked > 0)
{
ItemHelper.SetIsChecked((d as Person).GetValue(ItemHelper.ParentProperty) as DependencyObject, null);
return;
}
if (checked > 0)
{
ItemHelper.SetIsChecked((d as Person).GetValue(ItemHelper.ParentProperty) as DependencyObject, true);
return;
}
ItemHelper.SetIsChecked((d as Person).GetValue(ItemHelper.ParentProperty) as DependencyObject, false);
}
}
public static void SetIsChecked(DependencyObject element, bool? IsChecked)
{
element.SetValue(ItemHelper.IsCheckedProperty, IsChecked);
}
public static bool? GetIsChecked(DependencyObject element)
{
return (bool?)element.GetValue(ItemHelper.IsCheckedProperty);
}
public static readonly DependencyProperty ParentProperty = DependencyProperty.RegisterAttached("Parent", typeof(object), typeof(ItemHelper));
public static void SetParent(DependencyObject element, object Parent)
{
element.SetValue(ItemHelper.ParentProperty, Parent);
}
public static object GetParent(DependencyObject element)
{
return (object)element.GetValue(ItemHelper.ParentProperty);
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication102.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication102"
Title="MainWindow" Height="220" Width="250">
<StackPanel>
<TreeView x:Name="treeView" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Families}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Family}" ItemsSource="{Binding Members}" >
<CheckBox Content="{Binding Name}" IsChecked="{Binding Path=(local:ItemHelper.IsChecked), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(local:ItemHelper.IsChecked)}" Value="False" >
<Setter Property="Foreground" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:Person}" >
<CheckBox Content="{Binding Name}" IsChecked="{Binding Path=(local:ItemHelper.IsChecked), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(local:ItemHelper.IsChecked)}" Value="False" >
<Setter Property="Foreground" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
</DataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</TreeView.ItemContainerStyle&g以上是关于如何使用wpf中的复选框开发树视图?的主要内容,如果未能解决你的问题,请参考以下文章