我有一个绑定到集合的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之间会有来自其他行的值,它就是&#39 ;如果我向上和向下滚动DataGrid,那就特别糟糕。
在另一个问题中,我发现了这个链接,Collection-Type Dependency Properties,这与我的案例并不相似,但似乎相似。他们在构造函数中建议SetValue(),并将属性的默认值设置为新实例。我尝试将其设置为null但它似乎完全禁用了我的数据绑定。
SetValue(Board1Property, null);
我的猜测是因为DependencyProperties是静态的,并且因为我的DependencyProperty是一个类,所以在我的BoardValueDifference用户控件的实例之间进行某种共享。我该如何解决?我认为它可能与this question类似,但我不能很好地理解答案,以便解决我的问题。
在我的UserControl中添加一些日志记录后,我想我知道发生了什么:
总而言之,我可以解决这个问题,但如果有人有更好的解决方法或者确切知道DataGrid中UserControl的生命周期应该如何工作,我将不胜感激。
答案 0 :(得分:1)
由于行虚拟化,您的UserControl会被回收。如果DataGrid中没有太多行,则可以通过将EnableRowVirtualization
属性设置为false来禁用此行为。
在DataGrid.EnableRowVirtualization页面的备注部分:
要提高性能,请将EnableRowVirtualization属性设置为 默认为true。当EnableRowVirtualization属性设置为 true,DataGrid不为每个实例化DataGridRow对象 绑定数据源中的数据项。而是,DataGrid创建 DataGridRow仅在需要时才对象,并重用它们 尽可能。例如,DataGrid为其创建DataGridRow对象 当前处于视图中的每个数据项,并在其中回收该行 滚动出视图。