簡體   English   中英

ObservableCollection CollectionChanged更新datagrid

[英]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綁定到DataGridSource ,那么它應該按預期工作。
當添加新項目或刪除項目時,將通知您的視圖以更新其數據。

要跟蹤你不需要實現您的列表的CollectionChanged事件的實際變化,但你必須做出的排行榜中的實際對象觀測 要使對象可觀察,您必須實現INotifyPropertyChanged接口。
一旦對象可觀察,並且屬性發出PropertyChanged通知,observable集合將捕獲此信息。

以下是一些快速示例代碼,可幫助您入門:

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;
    }
}

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); }
    } 
}

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); }
    } 
}

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>

您應該直接添加到綁定集合。 添加到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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM