C# WPF DataGrid旧编辑元素导致问题
WPF数据网格(.NET 4.5.1)不会自动销毁旧的编辑元素。考虑下面的小例子: XAML:C# WPF DataGrid旧编辑元素导致问题,c#,wpf,wpfdatagrid,C#,Wpf,Wpfdatagrid,WPF数据网格(.NET 4.5.1)不会自动销毁旧的编辑元素。考虑下面的小例子: XAML: <Window .... xmlns:wa="clr-namespace:WpfApplication1"> .... <DataGrid Name="dataGrid" AutoGenerateColumns="False" Height="200" CanUserAddRows="False"> <DataGrid.Co
<Window ....
xmlns:wa="clr-namespace:WpfApplication1">
....
<DataGrid Name="dataGrid" AutoGenerateColumns="False" Height="200" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="testCol">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TestText}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<wa:MyTextBox Text="{Binding TestText}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
再重复一遍,您将看到多个旧的编辑元素不断触发TextChanged事件
这给我带来了问题,因为我有两列-Amount
和AmountUnit
Amount
的编辑元素有一个NumericUpDown,而AmountUnit
将指定NumericUpDown的小数位数。当然,NumericUpDown有一个强制值方法,该方法将值约束到指定的小数位数。问题是,所有旧的NumericUpDown编辑元素都在相互重叠并重新写入Amount
值,而此时它们应该被垃圾收集
所以我的问题是,如何在单元格完成编辑后立即销毁或垃圾收集旧的编辑元素?或者这个问题的(简单的)解决方法是什么?我想出来了:)
问题是DataGridTemplateColumn在其元素卸载后不会自动清除其绑定。也许,因为您可以定义非常复杂的元素,而自动执行将非常困难和耗时
通过反射器查看DataGridTextColumn,我得出结论,我必须手动执行此操作,因为DataGridTextColumn还可以在内部清除绑定
我现在面临的问题是,清除绑定的标准方法都不起作用:
// For instance, I Added a MyTextBox_Unloaded event handler and tried calling:
private void MyTextBox_Unloaded(object sender, RoutedEventArgs e)
{
// none of these worked
(sender as MyTextBox).ClearValue(MyTextBox.TextProperty); // this is what DataGridTextColumn internally uses
BindingOperations.ClearAllBindings((sender as MyTextBox));
(sender as MyTextBox).SetValue(MyTextBox.TextProperty, null);
(sender as MyTextBox).Text = null;
BindingOperations.ClearBinding((sender as MyTextBox), MyTextBox.TextProperty);
}
// I also tried, this:
private void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
var cp = e.EditingElement as ContentPresenter;
var child = (VisualTreeHelper.GetChild(cp, 0) as UIElement);
BindingOperations.ClearBinding(cp.BindingGroup.BindingExpressions[0].Target, cp.BindingGroup.BindingExpressions[0].TargetProperty);
(child as MyTextBox).ClearValue(MyTextBox.TextProperty);
BindingOperations.ClearAllBindings(child as MyTextBox);
cp.BindingGroup.BindingExpressions.Clear();
}
但最后我偶然发现了这一点,它确实起了作用:
private void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.Column is DataGridTemplateColumn)
{
BindingOperations.ClearAllBindings(e.EditingElement as ContentPresenter);
}
}
我花了几个小时解决一个问题,然后发现我错过了这一行
var child=(visualtreeheloper.GetChild(cp,0)作为UIElement)代码>
// For instance, I Added a MyTextBox_Unloaded event handler and tried calling:
private void MyTextBox_Unloaded(object sender, RoutedEventArgs e)
{
// none of these worked
(sender as MyTextBox).ClearValue(MyTextBox.TextProperty); // this is what DataGridTextColumn internally uses
BindingOperations.ClearAllBindings((sender as MyTextBox));
(sender as MyTextBox).SetValue(MyTextBox.TextProperty, null);
(sender as MyTextBox).Text = null;
BindingOperations.ClearBinding((sender as MyTextBox), MyTextBox.TextProperty);
}
// I also tried, this:
private void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
var cp = e.EditingElement as ContentPresenter;
var child = (VisualTreeHelper.GetChild(cp, 0) as UIElement);
BindingOperations.ClearBinding(cp.BindingGroup.BindingExpressions[0].Target, cp.BindingGroup.BindingExpressions[0].TargetProperty);
(child as MyTextBox).ClearValue(MyTextBox.TextProperty);
BindingOperations.ClearAllBindings(child as MyTextBox);
cp.BindingGroup.BindingExpressions.Clear();
}
private void dataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.Column is DataGridTemplateColumn)
{
BindingOperations.ClearAllBindings(e.EditingElement as ContentPresenter);
}
}