Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF DataGrid旧编辑元素导致问题_C#_Wpf_Wpfdatagrid - Fatal编程技术网

C# WPF DataGrid旧编辑元素导致问题

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

WPF数据网格(.NET 4.5.1)不会自动销毁旧的编辑元素。考虑下面的小例子:

XAML:

    <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);
    }
}