【发布时间】:2016-05-04 19:42:23
【问题描述】:
我有一个绑定到集合的 WPF DataGrid。 DataGrid 的列之一是包含我的自定义控件的 DataGridTemplateColumn:
<DataGridTemplateColumn Header="$ Diff" Width="60*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ui:BoardValueDifference Board1="{Binding Board1}" Board2="{Binding Board2}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
我的自定义控件有两个依赖属性,Board1 和 Board2,非常标准的东西。
public BoardValueDifference()
{
InitializeComponent();
}
public static readonly DependencyProperty Board1Property = DependencyProperty.Register("Board1", typeof(PackageBoard),
typeof(BoardValueDifference), new FrameworkPropertyMetadata(OnDataChanged));
public PackageBoard Board1
{
get { return (PackageBoard)GetValue(Board1Property); }
set { SetValue(Board1Property, value); }
}
protected static void OnDataChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
BoardValueDifference bvd = d as BoardValueDifference;
if ( bvd != null )
bvd.CalculateDifference();
}
protected void CalculateDifference()
{
if ( Board1 != null && Board2 != null) {
// Calculate value difference between boards
}
}
我的问题是 Board1 和 Board2 似乎是不确定的,我正在从其他行获取值。如果我在 OnDataChanged() 中设置断点,我会看到它被 Board1 的数据绑定击中,然后被 Board2 的数据绑定击中,但在 Board2 之间会有来自其他行的值,如果我向上和向下滚动我的 DataGrid,这尤其糟糕。
从另一个问题中,我找到了这个链接,Collection-Type Dependency Properties,它不是针对我的情况,但看起来很相似。他们建议在构造函数中使用 SetValue() 并将属性的默认值设置为新实例。我尝试将其设置为 null,但它似乎完全禁用了我的数据绑定。
SetValue(Board1Property, null);
我的猜测是,因为 DependencyProperties 是静态的,并且因为我的 DependencyProperty 是一个类,所以我的 BoardValueDifference 用户控件的实例之间存在某种共享。我该如何解决?我认为它可能类似于this question,但我对回复的理解不足以解决我的问题。
更新
在我的 UserControl 添加一些日志记录后,我想我明白了发生了什么:
- 我曾假设DataGrid 的每一行都会获得我的UserControl 的一个新实例,而Board1 和Board2 将从null 开始。根据我的日志,BoardValueDifference 被重新使用,只是更改了 DependencyProperties。
- 在我的代码中,当 Board1 和 Board2 不再为空时,我正在计算板之间的差异。我意识到我现在不能这样做,但是在我的 UserControl 中有剩余的数据感觉非常草率。我猜你得把它想成一个静态类?
底线,我可以解决这个问题,但如果有人有更好的解决方法或确切知道 DataGrid 中 UserControl 的生命周期应该如何工作,我将不胜感激。
【问题讨论】:
-
为什么使用
PropertyDescriptor.AddValueChanged而不是直接注册一个PropertyChangedCallback 将PropertyMetadata传递给DependencyProperty.Register? -
没有具体原因,我在尝试解决此错误时曾在两种方法之间切换并没有返回。如果我没记错的话我在这里的方式can lead to a memory leak?
-
使用 PropertyChangedCallback。这另一种方法很奇怪。
-
为了让你开心而改变,但与根本问题无关,无论哪种方式都是同样的问题。
-
还有一点,Board1 和 Board2 绑定上的
UpdateSourceTrigger=PropertyChanged没有意义。它只对双向绑定有效。
标签: c# wpf dependency-properties