ObservableCollection CollectionChanged更新datagrid

mit*_*mit 3 c# wpf datagrid observablecollection

我有一个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));
    }
Run Code Online (Sandbox Code Playgroud)

这就是我以前的所作所为

OrderListData.Clear();
foreach (OrderListViewModel Order in OrderList)
{
      OrderListData.Add(new OrderList(Order.Description, Order.OrderId));
}
m_OrderListDataCollection.Clear();
OrderListData.ToList().ForEach(m_OrderListDataCollection.Add);
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

编辑: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;
Run Code Online (Sandbox Code Playgroud)

Oce*_*ans 5

如果你只是绑定ObservableCollectionSource你的DataGrid那个它应该按预期工作.
当添加新项目或删除项目时,将通知您的视图以更新其数据.

要跟踪你的实际变化并不需要执行列表的CollectionChanged事件,但你必须做出的排行榜中的实际对象观察到的.要使对象可观察,您必须实现该INotifyPropertyChanged接口.
一旦对象可观察,并且属性发出PropertyChanged通知,则可观察集合将捕获此信息.

以下是一些快速示例代码,可帮助您入门:

1.为可观察对象创建自己的实现

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

2.让您的实际对象类扩展此实现,并确保必要的属性发送PropertyChanged通知

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); }
    } 
}
Run Code Online (Sandbox Code Playgroud)

3.确保您的ViewModel具有ObservableCollection

(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); }
    } 
}
Run Code Online (Sandbox Code Playgroud)

4.将DataGrid的源绑定到ObservableCollection

<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>
Run Code Online (Sandbox Code Playgroud)