【发布时间】:2018-07-05 23:29:08
【问题描述】:
我有一个DataGrid,它绑定到ObservableCollection。我有一个动态数据列表,因此正在从列表中编辑/添加/删除项目。
起初,我正在清除并添加ObservableCollection,但后来我发现我可以刷新ObservableCollection,我需要为此实现CollectionChanged,但我不确定是否有任何机构可以提供一些指示或很棒的示例代码。
private List<OrderList> m_OrderListData = new List<OrderList>();
public List<OrderList> OrderListData
{
get => m_OrderListData;
private set => Set(ref m_OrderListData, value);
}
private ObservableCollection<OrderList> m_OrderListDataCollection;
public ObservableCollection<OrderList> OrderListDataCollection
{
get => m_OrderListDataCollection;
private set => Set(ref m_OrderListDataCollection, value);
}
...
...
m_OrderListDataCollection = new ObservableCollection<OrderList>(m_OrderListData as List<OrderList>);
...
...
foreach (OrderListViewModel Order in OrderList)
{
OrderListData.Add(new OrderList(Order.Description, Order.OrderId));
}
这是我之前的经历
OrderListData.Clear();
foreach (OrderListViewModel Order in OrderList)
{
OrderListData.Add(new OrderList(Order.Description, Order.OrderId));
}
m_OrderListDataCollection.Clear();
OrderListData.ToList().ForEach(m_OrderListDataCollection.Add);
XAML
<Label Content="OrderList"/>
<DataGrid Name="dgOrderList"
AutoGenerateColumns="False"
ItemsSource="{Binding Path=OrderListDataCollection}"
IsReadOnly="True"
SelectionMode="Single"
SelectionUnit="FullRow">
<DataGrid.Columns>
<DataGridTextColumn Width="Auto" Header="ID" Binding="{Binding OrderId}"/>
<DataGridTextColumn Width="*" Header="Description" Binding="{Binding OrderDescription}"/>
</DataGrid.Columns>
</DataGrid>
编辑: 订单列表类
public class OrderList : INotifyPropertyChanged
{
private string m_OrderDescription;
private string m_OrderId;
public string OrderDescription
{
get => m_OrderDescription;
set => Set(ref m_OrderDescription, value);
}
public string OrderId
{
get => m_OrderId;
set => Set(ref m_OrderId, value);
}
#region Constructor
public OrderList()
{
}
public OrderList(string description, string id)
{
m_OrderDescription = description;
m_OrderId = id;
}
#endregion
#region INotifyPropertyChanged
/// <summary>Updates the property and raises the changed event, but only if the new value does not equal the old value. </summary>
/// <param name="PropName">The property name as lambda. </param>
/// <param name="OldVal">A reference to the backing field of the property. </param>
/// <param name="NewVal">The new value. </param>
/// <returns>True if the property has changed. </returns>
public bool Set<U>(ref U OldVal, U NewVal, [CallerMemberName] string PropName = null)
{
VerifyPropertyName(PropName);
return Set(PropName, ref OldVal, NewVal);
}
/// <summary>Updates the property and raises the changed event, but only if the new value does not equal the old value. </summary>
/// <param name="PropName">The property name as lambda. </param>
/// <param name="OldVal">A reference to the backing field of the property. </param>
/// <param name="NewVal">The new value. </param>
/// <returns>True if the property has changed. </returns>
public virtual bool Set<U>(string PropName, ref U OldVal, U NewVal)
{
if (Equals(OldVal, NewVal))
{
return false;
}
OldVal = NewVal;
RaisePropertyChanged(new PropertyChangedEventArgs(PropName));
return true;
}
/// <summary>Raises the property changed event. </summary>
/// <param name="e">The arguments. </param>
protected virtual void RaisePropertyChanged(PropertyChangedEventArgs e)
{
var Copy = PropertyChanged;
Copy?.Invoke(this, e);
}
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
protected virtual void VerifyPropertyName(string PropertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[PropertyName] == null)
{
string ErrorMsg = "Invalid Property Name: " + PropertyName + "!";
if (ThrowOnInvalidPropertyName)
{
throw new Exception(ErrorMsg);
}
Debug.Fail(ErrorMsg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; } = true;
【问题讨论】:
-
如果您只是将
ObservableCollection绑定到Source的DataGrid,那么它应该可以按预期工作。每当添加新项目或删除项目时,您的视图将收到通知以更新其数据。要跟踪实际更改,您不需要需要实现列表的 CollectionChanged 事件,但您必须使列表中的实际对象可观察。一旦对象是可观察的,并且一个属性发送了一个PropertyChangednotification,可观察的集合就会捕捉到这个。 -
它绑定到数据网格,但通过实现,数据网格中没有填充任何内容。我至少之前的实现确实可以填充数据并更新它,但我想避免清除集合,因为我无法在数据网格中选择一个项目。
-
你能发布你的 OderList 类吗?它应该这样声明: public class OrderList : INotifyPropertyChanged 并包含一个私有的 void NotifyPropertyChanged 方法(如下面 Daniele 的回答所示)。然后在 ObservableCollection 中使用该类,您将被覆盖。
-
@PaulGibson 查看帖子编辑
标签: c# wpf datagrid observablecollection