DataGrid会导致BeginEdit()方法运行两次 [英] DataGrid causes BeginEdit() method to run twice

查看:224
本文介绍了DataGrid会导致BeginEdit()方法运行两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为 ViewModel 实现了 IEditableObject ,下面的控件就被绑定了。

I have implemented IEditableObject for my ViewModel and the below controls are bound to it.

现在,当我第一次启动包含这些控件的窗口时, BeginEdit ()方法运行并备份变量。

Now when the first time I fire up the Window containing these controls, the BeginEdit() method runs and backs up the variables.

我的问题是这样的:当我开始编辑 DataGrid c $ c> BeginEdit()方法运行并将更改保存到我已经备份的变量中!这样会破坏 BeginEdit() CancelEdit()的目的。现在如果我选择取消窗口,我将不会拥有原始数据。如何防止这种情况?

My problem is this: When I start editing the DataGrid again the BeginEdit() method runs and saves the changes to my already backed up variables! This ruins the purpose of the BeginEdit() and CancelEdit(). Now if I choose to cancel the Window, I won't have the original data. How can I prevent this?

<ComboBox ItemsSource="{Binding Path=CoatingFactors}"
          SelectedItem="{Binding Path=CoatingFactor}">
</ComboBox>

<DataGrid ItemsSource="{Binding Path=CustomCFactors}"                      
  ....
</DataGrid>

这是我如何实现 BeginEdit() CancelEdit()方法:

Here is how I have implemented the BeginEdit() and CancelEdit() methods:

private List<CustomCFactorItem> customCFactors_ORIGINAL;
private double coatingFactor_ORIGINAL;


public void BeginEdit()
{
    customCFactors_ORIGINAL = customCFactors.ConvertAll(o => o.Clone()).ToList();
    coatingFactor_ORIGINAL = coatingFactor;
}

public void CancelEdit()
{
    customCFactors = customCFactors_ORIGINAL.ConvertAll(o => o.Clone()).ToList();
    coatingFactor = coatingFactor_ORIGINAL;
}

更新:

现在,我正在使用这样一个小黑客:

For now, I'm using a little hack like this:

    private List<CustomCFactorItem> customCFactors_ORIGINAL;
    private double coatingFactor_ORIGINAL;

    private int editNum = 0;

    public void BeginEdit()
    {
        if (editNum > 0) return;

        editNum++;

        customCFactors_ORIGINAL = customCFactors.ConvertAll(o => o.Clone());
        coatingFactor_ORIGINAL = coatingFactor;
    }

    public void EndEdit()
    {
        editNum = 0;
    }

    public void CancelEdit()
    {
        editNum = 0;

        customCFactors = customCFactors_ORIGINAL.ConvertAll(o => o.Clone());
        coatingFactor = coatingFactor_ORIGINAL;
    }


推荐答案

最好不要与UI层的WPF DataGrid 控件。没有为自己的目的编写自己的控件,你根本不会赢得这场战斗。总会有另一个微软骗子来处理。我建议从 ObservableCollection 的避风港中实现所需的行为。

It's best not to fight with the WPF DataGrid control at the UI layer. Without writing your own controls designed to suit your own purposes, you simply won't win that fight. There will always be another Microsoft "gotcha" to deal with. I recommend implementing the desired behaviour from the safe-haven of an ObservableCollection.

public class ViewModel
{
    public ViewModel()
    {
        CustomCFactors.CollectionChanged += (s, e) => {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (CustomCFactorItem item in e.NewItems)
                        item.PropertyChanged += BackupLogicEventHandler;
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (CustomCFactorItem item in e.OldItems)
                        item.PropertyChanged -= BackupLogicEventHandler;
                    break;
            }
        };
        for (int i = 0; i < 10; ++i)
        {
            CustomCFactors.Add(new CustomCFactorItem("one", "two", "three"));
        }
        ExecuteBackupLogic();

    }

    public ObservableCollection<CustomCFactorItem> CustomCFactors { get; set; } = new ObservableCollection<CustomCFactorItem>();

    public void BackupLogicEventHandler(object sender, PropertyChangedEventArgs e){
        ExecuteBackupLogic();
    }
    public void ExecuteBackupLogic()
    {
        Console.WriteLine("changed");
    }
}

这是一个例子, CustomCFactorItem 可能看起来像

And Here's a sample of what CustomCFactorItem might look like

public class CustomCFactorItem : INotifyPropertyChanged
    {
        private string _field1 = "";
        public string Field1
        {
            get
            {
                return _field1;
            }
            set
            {
                _field1 = value;
                RaisePropertyChanged("Field1");
            }
        }
        private string _field2 = "";
        public string Field2
        {
            get
            {
                return _field2;
            }
            set
            {
                _field2 = value;
                RaisePropertyChanged("Field2");
            }
        }
        private string _field3 = "";
        public string Field3
        {
            get
            {
                return _field3;
            }
            set
            {
                _field3 = value;
                RaisePropertyChanged("Field1");
            }
        }
        public CustomCFactorItem() { }
        public CustomCFactorItem(string field1, string field2, string field3)
        {
            this.Field1 = field1;
            this.Field2 = field2;
            this.Field3 = field3;
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string property)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
        }
    }

这是一个简单的视图,将集合绑定到 DataGrid 。请注意,每次进行编辑时,输出都会写入控制台。

And this is a simple View that binds the collection to DataGrid. Notice that output is written to the console each time an edit is made.

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Grid>
        <DataGrid ItemsSource="{Binding CustomCFactors}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Field 1" Binding="{Binding Field1, UpdateSourceTrigger=PropertyChanged}" />
                <DataGridTextColumn Header="Field 2" Binding="{Binding Field2, UpdateSourceTrigger=PropertyChanged}" />
                <DataGridTextColumn Header="Field 3" Binding="{Binding Field3, UpdateSourceTrigger=PropertyChanged}" />
            </DataGrid.Columns>

        </DataGrid>
    </Grid>
</Window>

这篇关于DataGrid会导致BeginEdit()方法运行两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆