[英]WPF TreeView Binding not updating the View
INotifyPropertyChanged 已实现,DataContext 已设置。
这是我的 TreeView:
<TreeView ItemContainerStyle="{StaticResource MaterialDesignTreeViewItemExtended}" x:Name="TestCasesTree" MinWidth="220" ItemsSource="{Binding TestCases.Children, Mode=TwoWay}">
<i:Interaction.Behaviors>
<behaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedTreeViewItem, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<TreeView.Resources>
<con:TestAssessmentToImagePathConverter x:Key="TestAssessmentConverter" />
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children, Mode=TwoWay}" DataType="{x:Type data:TestCaseNode}">
<StackPanel Margin="0" Orientation="Horizontal">
<Image Source="{Binding TestAssessment, Converter={StaticResource TestAssessmentConverter}}" RenderOptions.BitmapScalingMode="HighQuality" Width="20" Height="20"/>
<TextBlock Margin="8 2 0 0" Text="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
捆绑:
ItemsSource="{Binding TestCases.Children, Mode=TwoWay}"
可绑定基础 class:
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
{
if (Equals(storage, value))
{
return false;
}
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected bool CanExecute
{
get
{
return true;
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
财产:
public TestCaseNode TestCases
{
get { return mainWindowModel.TestCases; }
set
{
mainWindowModel.TestCases = value;
SetProperty(ref _testCases, value);
}
}
孩子们:
public ObservableCollection<TestCaseNode> Children { get; set; }
我编辑东西的地方:
SelectedTreeViewItem.SetTestAssessmentForCluster(testAssessment);
OnPropertyChanged("Children");
OnPropertyChanged("TestCases");
OnPropertyChanged(nameof(TestCases));
OnPropertyChanged(nameof(TestCases.Children));
View 没有任何变化(但是当我在 Visual Studio 中调试它时,我清楚地看到 object 发生了变化)
这行得通,但它使其他事情崩溃:
SelectedTreeViewItem.SetTestAssessmentForCluster(testAssessment);
var tc = TestCases;
TestCases = null;
TestCases = tc;
升级版:
测试用例节点 Class:
public class TestCaseNode : TestCase, IEquatable<TestCaseNode>, IComparable<TestCaseNode>
{
public TestCaseNode Parent { get; set; }
public ObservableCollection<TestCaseNode> Children { get; set; }
public void Add(TestCaseNode node) {...}
public void SetTestAssessmentForCluster(TestAssessment testAssessment, ref TestScores _testScores) {...}
public bool Equals(TestCaseNode other) {...}
public override bool Equals(object obj) {...}
public override int GetHashCode() {...}
public int CompareTo(TestCaseNode other) {...}
}
测试用例 Class:
public class TestCase
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TestStep> TestSteps { get; set; }
public TestAssessment TestAssessment { get; set; } = TestAssessment.EMPTY;
}
OnPropertyChanged("TestCases");
必须由包含已更改属性的 object 颁发。 在您的情况下,您的 class TestCaseNode
将需要调用OnPropertyChanged
方法,以便 Treeview 识别对集合的更改,因为 object 持有集合。 也就是说,更改的不仅仅是一些名为"TestCases"
的属性,而是特定 object 中的属性。 原因:您可以在不同的类中拥有多个具有此名称的属性。 并且,如果 object 有多个副本,则它们每个都有同名的属性。
我所做的,这对我有用,是在TestCaseNode
中添加一个名为UpdateProperties()
的公共方法,然后调用OnPropertyChanged("TestCases");
这可确保由正确的 object 发出属性更新。 然后当我需要更新控件时调用此方法。
还有其他几种方法可以做同样的事情,但我发现这是一种简单直接的方法。 例如,您可以包括 `OnPropertyChanged("TestCases"); 在您的添加方法中。 我没有这样做是因为 1) OnPropertyChanged 调用发生得太频繁,并且 2) 如果没有 OnPropertyChanged 调用,我可以推迟对控件的更新,直到我完成了几个或全部 Add 之后。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.