我有一个小的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中,如果可能的话,如何做到这一点?如果不可能,如何实现类似的东西?
答案 0 :(得分:1)
你有一个实现INotifyPropertyChanged
的课程吗?
您可以订阅ObservableCollection
events。 CollectionChange
可能会做到这一点但不利用数据绑定。
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;