为什么在更改ObservableCollection中的数据时不更新DataGrid数据?

时间:2016-04-26 21:07:39

标签: c# wpf datagrid

我有一个小的DataGrid来做一个简单的操作。字段为3:数字1,2和结果数字。 DataGrid代码如下:

<DataGrid x:Name="dgNumbers" ItemsSource="{Binding lstOperations, Mode=TwoWay}" CanUserAddRows="True" AutoGenerateColumns="False" CellEditEnding="dgNumbers_CellEditEnding">
     <DataGrid.Columns>
         <DataGridTextColumn Header="Number 1" Width="*" Binding="{Binding N1, Mode=TwoWay}"/>
         <DataGridTextColumn Header="Number 2" Width="*" Binding="{Binding N2, Mode=TwoWay}"/>
         <DataGridTextColumn Header="Result" Width="*" Binding="{Binding Result, Mode=TwoWay}" IsReadOnly="True"/>
     </DataGrid.Columns>
 </DataGrid>

我创建了一个对象,我保留数字1,数字和结果。这是类代码:

public class Numbers
{
    public decimal N1 { get; set; }
    public decimal N2 { get; set; }
    public decimal Result { get; set; }
}

我做了一个小例子来试图理解构成ObservableCollection的Binding。 对于此示例,我在事件中有以下代码:

public MainWindow()
{
    InitializeComponent();
    lstOperations = new ObservableCollection<Numbers>();
}

ObservableCollection<Numbers> lstOperations;

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Numbers n = new Numbers();
    n.N1 = 10;
    n.N2 = 5;
    n.Result = 15;
    lstOperations.Add(n);
    dgNumbers.ItemsSource = lstOperations;
}

private void dgNumbers_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    foreach(var item in lstOperations)
    {
        item.Result = item.N1 + item.N2;
    }
}

我想知道如果更改数据集合,这个事实会反映在DataGrid中,如果可能的话,如何做到这一点?如果不可能,如何实现类似的东西?

3 个答案:

答案 0 :(得分:1)

你有一个实现INotifyPropertyChanged的课程吗?

您可以订阅ObservableCollection eventsCollectionChange可能会做到这一点但不利用数据绑定。

public MainWindow()
{
    InitializeComponent();
    lstOperations = new ObservableCollection<Numbers>();
    lstOperations.CollectionChanged += MyCollectionChanged;
}

private MyCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    dgNumbers.ItemsSource = lstOperations;

}

所以基本的数据绑定就是这样的。

public class ModelView : INotifyPropertyChanged
{

    public ModelView()
    {
    lstOperations = new ObservableCollection<Numbers>();
    lstOperations.CollectionChanged += new NotifyCollectionChangedEventHandler((obj, e) => { OnPropertyChanged("lstOperations "); });
    }
 //-----------------  Implementing the interface here
     public event PropertyChangedEventHandler PropertyChanged;

     // Call this method when you want the GUI updated.
     public void OnPropertyChanged(string PropertyName)
     {
        if (PropertyChanged != null)
           PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
     }
//-------------------Your Properties-----------------------------
    private  ObservableCollection<Numbers> _lstOperations ;

    public  ObservableCollection<Numbers> lstOperations
    {
        get{return _lstOperations ;}
        set
        {
        _lstOperations = value;
        OnPropertyChanged("lstOperations");
        }   

    }

好的,上面的类现在包含你想要绑定的变量。现在,您需要为Datagrid设置datacontext。

    // Need your model instance.
private ModelView Model;

public MainWindow()
    {
        InitializeComponent();
        Model = new ModelView();
        dgNumbers.DataContext = Model;
    }

现在你操纵lstOperations的任何地方都操纵Model.lstOperations

答案 1 :(得分:1)

您也可以通过NuGet Prism.Core安装并使用BindableBase类:

using Prism.Mvvm;
using System.Collections.ObjectModel;
using System.Windows;

namespace YourApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }

        private void dgNumbers_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
        {
            foreach (var item in (DataContext as MainWindowViewModel).LstOperations)
            {
                item.Result = item.N1 + item.N2;
            }
        }
    }

    public class MainWindowViewModel : BindableBase
    {
        private ObservableCollection<Numbers> _lstOperations;

        public ObservableCollection<Numbers> LstOperations
        {
            get { return _lstOperations; }
            set
            {
                _lstOperations = value;
                OnPropertyChanged();
            }
        }

        public MainWindowViewModel()
        {
            _lstOperations = new ObservableCollection<Numbers>();
            Numbers n = new Numbers
            {
                N1 = 10,
                N2 = 5,
                Result = 15
            };
            LstOperations.Add(n);
        }
    }

    public class Numbers : BindableBase
    {
        private decimal _n1;
        public decimal N1
        {
            get { return _n1; }
            set { SetProperty(ref _n1, value); }
        }

        private decimal _n2;
        public decimal N2
        {
            get { return _n2; }
            set { SetProperty(ref _n2, value); }
        }

        private decimal _result;
        public decimal Result
        {
            get { return _result; }
            set { SetProperty(ref _result, value); }
        }
    }
}

最后,您还必须在视图中更改绑定:

   <DataGrid x:Name="dgNumbers" ItemsSource="{Binding LstOperations, Mode=TwoWay}" CanUserAddRows="True" AutoGenerateColumns="False" CellEditEnding="dgNumbers_CellEditEnding">

使用BindableBase非常简单,因为它在实现中采用了CallerMemberName属性,因此您不必指定调用哪个属性(您在setter中编写OnPropertyChanged()而不是OnPropertyChanged(“propertyName”))。它甚至更好,因为还有SetProperty方法,它设置新值AND仅在需要时调用OnPropertyChanged事件(当新值真的是新的,真正改变时)。

答案 2 :(得分:-1)

请原谅我的愚蠢提示,但对我而言,当我绑定这样一个列表

时,它会起作用
    public class ModelNumber
{
    public decimal N1 { get; set; }
    public decimal N2 { get; set; }
    public decimal Result { get; set; }
}

public class ViewModelNumber : NotifyPropertyChanged, IDataErrorInfo
{
    protected ModelNumber __dataModel = null;


    #region ---constructor---


    public ViewModelNumber()
    {
        // model init
        this.__dataModel = new ModelNumber();
    }


    #endregion
    #region ---accessoren model basis---


    public decimal N1
    {
        get
        {
            return this.__dataModel.N1;
        }
        set
        {
            if (this.__dataModel.N1 != value)
            {
                this.__dataModel.N1 = value;
                this.OnPropertyChanged("N1");
            }
        }
    }

    public decimal N2
    {
        get
        {
            return this.__dataModel.N2;
        }
        set
        {
            if (this.__dataModel.N2 != value)
            {
                this.__dataModel.N2 = value;
                this.OnPropertyChanged("N1");
            }
        }
    }

    public decimal Result
    {
        get
        {
            return this.__dataModel.Result;
        }
        set
        {
            if (this.__dataModel.Result != value)
            {
                this.__dataModel.Result = value;
                this.OnPropertyChanged("N1");
            }
        }
    }


    #endregion
    #region ---validation---


    /// <summary>Gets an error message indicating what is wrong with this object.</summary>
    public string Error
    {
        get { throw new NotImplementedException(); }
    }

    /// <summary>Gets the error message for the property with the given name.</summary>
    public string this[string _columnName]
    {
        get
        {

            try
            {
                if (_columnName != null)
                {
                    switch (_columnName)
                    {
                        default:
                            break;
                    }
                }

                return (null);
            }
            catch (Exception _except)
            {
                // mlog
                Log.Exception(this.GetType().FullName, MethodBase.GetCurrentMethod().Name, _except);

                return (null);
            }
        }
    }


    #endregion
}

ObservableCollection<ViewModelNumber> lstOperations;
相关问题