Binding WPF-绑定到复选框在HierarchycalDataTemplate中不起作用
在WPF树视图中,如果正在检查父节点,我将尝试自动检查子节点。我正在使用一个视图模型和一个可绑定的对象,但是我所有的尝试都失败了。下面是代码(C#+XAML)。任何想法都将不胜感激Binding WPF-绑定到复选框在HierarchycalDataTemplate中不起作用,binding,checkbox,hierarchicaldatatemplate,Binding,Checkbox,Hierarchicaldatatemplate,在WPF树视图中,如果正在检查父节点,我将尝试自动检查子节点。我正在使用一个视图模型和一个可绑定的对象,但是我所有的尝试都失败了。下面是代码(C#+XAML)。任何想法都将不胜感激 <Window x:Class="TestCheckBoxBinding.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/
<Window x:Class="TestCheckBoxBinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestCheckBoxBinding"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
<HierarchicalDataTemplate DataType="{x:Type local:TestCategory}" ItemsSource="{Binding Tests, Mode=OneTime}">
<Label Content="{Binding Name}"></Label>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Test}" ItemsSource="{Binding Children, Mode=OneTime}">
<StackPanel Orientation="Horizontal">
<CheckBox VerticalAlignment="Center" IsChecked="{Binding IsChecked, Mode=TwoWay}"></CheckBox>
<Label Content="{Binding Name}"></Label>
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding Categories, Mode=OneTime}"></TreeView>
</Grid>
公共类TestsViewModel
{
公共静态void PopulateList(TestsViewModel vm)
{
TestCategory cat1=newTestCategory(){Id=1,Name=“First category”};
testt1=newtest(){Name=“Test1”};
testt2=newtest(){Name=“Test2”};
Test t3=new Test(){Name=“Test3”};
t1.AddChild(t2);
t1.AddChild(t3);
测试t4=新测试(){Name=“Test4”};
cat1.AddTest(t1);
cat1.AddTest(t4);
vm.AddTestCategory(cat1);
TestCategory cat2=newTestCategory(){Id=2,Name=“Second category”};
Test t5=new Test(){Name=“Test1”};
测试t6=新测试(){Name=“Test2”};
Test t7=new Test(){Name=“Test3”};
t6.AddChild(t7);
Test t8=new Test(){Name=“Test4”};
cat2.AddTest(t5);
cat2.AddTest(t6);
cat2.AddTest(t8);
vm.AddTestCategory(cat2);
}
私有只读IEnumerable categories=新列表();
公共IEnumerable类别{get{return Categories;}}
公共void AddTestCategory(TestCategory TestCategory)
{
添加(testCategory);
}
}
公共类TestCategory
{
公共int Id{get;set;}
公共字符串名称{get;set;}
私有只读IEnumerable测试=新列表();
公共IEnumerable测试{get{return Tests;}}
公共测试(测试t)
{
((IList)测试)。添加(t);
}
}
公共类测试:INotifyPropertyChanged
{
私有字符串名称;
公共字符串名
{
设置
{
如果(名称!=值)
{
名称=值;
本协议项下的不动产变更(“名称”);
}
}
获取{返回名称;}
}
公共bool?isChecked=false;
公共场所被检查了
{
获取{return isChecked;}
设置
{
如果(已检查!=值)
{
isChecked=值;
if(children.Count()>0)
{
foreach(儿童var测试)
{
test.isChecked=值;
test.Name+=”;
}
}
本条关于财产的变更(“已检查”);
}
}
}
公共void AddChild(测试)
{
((IList)儿童)。添加(测试);
}
private readonly IEnumerable children=新列表();
可数儿童的公共教育
{
获取{返回子项;}
}
#区域INotifyProperty更改成员
//创建OnPropertyChanged方法以引发事件
受保护的void OnPropertyChanged(字符串propName)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(此,新PropertyChangedEventArgs(propName));
}
}
公共事件属性更改事件处理程序属性更改;
#端区
}
由于我没有设置子复选框的IsChecked属性,因此未选中子复选框。我正在设置isChecked字段,它绕过属性设置程序并防止引发PropertyChanged
public class TestsViewModel
{
public static void PopulateList(TestsViewModel vm)
{
TestCategory cat1 = new TestCategory() { Id = 1, Name = "First category" };
Test t1 = new Test() { Name = "Test1" };
Test t2 = new Test() { Name = "Test2" };
Test t3 = new Test() { Name = "Test3" };
t1.AddChild(t2);
t1.AddChild(t3);
Test t4 = new Test() { Name = "Test4" };
cat1.AddTest(t1);
cat1.AddTest(t4);
vm.AddTestCategory(cat1);
TestCategory cat2 = new TestCategory() { Id = 2, Name = "Second category" };
Test t5 = new Test() { Name = "Test1" };
Test t6 = new Test() { Name = "Test2" };
Test t7 = new Test() { Name = "Test3" };
t6.AddChild(t7);
Test t8 = new Test() { Name = "Test4" };
cat2.AddTest(t5);
cat2.AddTest(t6);
cat2.AddTest(t8);
vm.AddTestCategory(cat2);
}
private readonly IEnumerable<TestCategory> categories = new List<TestCategory>();
public IEnumerable<TestCategory> Categories { get { return categories; } }
public void AddTestCategory(TestCategory testCategory)
{
((IList<TestCategory>)categories).Add(testCategory);
}
}
public class TestCategory
{
public int Id { get; set; }
public string Name { get; set; }
private readonly IEnumerable<Test> tests = new List<Test>();
public IEnumerable<Test> Tests { get { return tests; } }
public void AddTest(Test t)
{
((IList<Test>)tests).Add(t);
}
}
public class Test : INotifyPropertyChanged
{
private string name;
public string Name
{
set
{
if (name != value)
{
name = value;
this.OnPropertyChanged("Name");
}
}
get { return name; }
}
public bool? isChecked = false;
public bool? IsChecked
{
get { return isChecked; }
set
{
if (isChecked != value)
{
isChecked = value;
if (children.Count() > 0)
{
foreach (var test in children)
{
test.isChecked = value;
test.Name += ".";
}
}
this.OnPropertyChanged("IsChecked");
}
}
}
public void AddChild(Test test)
{
((IList<Test>)children).Add(test);
}
private readonly IEnumerable<Test> children = new List<Test>();
public IEnumerable<Test> Children
{
get { return children; }
}
#region INotifyPropertyChanged Members
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string propName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}