![](/img/trans.png)
[英]Update XAML binding on CollectionChanged with ObservableCollection
[英]ObservableCollection CollectionChanged to update datagrid
我有一個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>
編輯:OrderList類
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
綁定到DataGrid
的Source
,那么它應該按預期工作。
當添加新項目或刪除項目時,將通知您的視圖以更新其數據。
要跟蹤你不需要實現您的列表的CollectionChanged事件的實際變化,但你必須做出的排行榜中的實際對象觀測 。 要使對象可觀察,您必須實現INotifyPropertyChanged
接口。
一旦對象可觀察,並且屬性發出PropertyChanged
通知,observable集合將捕獲此信息。
以下是一些快速示例代碼,可幫助您入門:
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propName));
}
}
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
}
public class Order : ObservableObject
{
private long _orderId;
public long OrderId
{
get { return _orderId; }
set { SetProperty(ref _orderId, value); }
}
private string _description;
public string Description
{
get { return _description; }
set { SetProperty(ref _description, value); }
}
}
(ViewModel也應該是可觀察的。我希望你已經是這種情況了,否則讓MVVM工作會非常困難。)
public class MyViewModel : ObservableObject
{
public MyViewModel()
{
//this is just an example of some test data:
var myData = new List<Order> {
new Order { OrderId = 1, Description = "Test1"},
new Order { OrderId = 2, Description = "Test2"},
new Order { OrderId = 3, Description = "Test3"}
};
//Now add the data to the collection:
OrderList = new ObservableCollection<Order>(myData);
}
private ObservableCollection<Order> _orderList;
public ObservableCollection<Order> OrderList
{
get { return _orderList; }
set { SetProperty(ref _orderList, value); }
}
}
<DataGrid Name="dgOrderList"
AutoGenerateColumns="False"
ItemsSource="{Binding OrderList, Mode=TwoWay}"
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>
您應該直接添加到綁定集合。 添加到OrderListData
不會影響您綁定的那個:
OrderListDataCollection.Add(new OrderList(Order.Description, Order.OrderId));
老實說,另一個看起來毫無價值,至少在它影響你的約束力的同時也是如此。 它所做的就是初始化ObservableCollection
。 它不是數據的持續來源。
首先需要在OrderList類中實現INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
然后你可以按原樣使用該集合。 如果要創建自定義事件,則使用CollectionChangedEvent,但默認情況下,ObservableCollection已通知UI更改其項目數。 您只需要通知UI有關單個項目的更改
編輯:將集合用作視圖模型中的屬性,該視圖模型也實現INotifyPropertyChanged
private ObservableCollection<MyItem> _myCollection = new ObservableCollection<MyItem>();
public ObservableCollection<MyItem> MyCollection
{
get {return _myCollection;}
set
{
_myCollection = value;
OnPropertyChanged("MyCollection");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.