【问题标题】:C# How to code EnableCollectionSynchronization for Collection of CollectionsC# 如何为集合集合编写 EnableCollectionSynchronization
【发布时间】:2015-11-30 21:53:37
【问题描述】:

我已经搜索了整个互联网以寻找没有结果的解决方案。 在我的程序中,我有 UI 线程,我在两个数据网格中显示客户和订单。显示所选客户的订单。集合的定义及其更新发生在后台。 UI 的目的只是显示最新信息。我利用了 C# 4.5 中引入的最新功能,即:BindingOperations.EnableCollectionSynchronization 方法。 在我的程序中,我有定义客户类集合的客户类。反过来,Customer 类定义了 Order 类的集合。我的问题是我不知道如何正确编码下面代码的最后一行,这与订单集合绑定同步有关。此代码已简化,我省略了 OnPropertyChange 代码行以确保在数据网格中显示正确的属性 - 我想专注于集合。

    public class Customers()
    {
       private ObservableCollection<Customer> _customerslist;
       public ObservableCollection<Customer> customerslist
       {get { 
            if (_customerslist == null)
            {_customerslist = new ObservableCollection<Customer>();}
            return _customerslist;
        }private set
        {_customerslist = value;}}
   }

   public class Customer
   {
       public customerID;
       public customerName;
       .....
       private ObservableCollection<Order> _orderslist;
       public ObservableCollection<Order> orderslist
       {get {if (_orderslist == null)
            {_orderslist = new ObservableCollection<Order>();}
            return _orderslist;
        } private set
        {_orderslist = value;}}
   }

public class MainWindow : Window
{
    private static object _syncLockCustomers = new object();
    private static object _syncLockOrders = new object();

    public MainWindow()
    {
    InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
    var firstCustomer = Customers.customerslist.FirstOrDefault();

        custDataGrid.DataContext = Customers.customerslist;
        if (firstCustomer != null)
        {
            custDataGrid.SelectedItem = firstCustomer;
            ordersDataGrid.DataContext = firstCustomer.Orders.orderslist;
        } 
BindingOperations.EnableCollectionSynchronization(Customers.customerslist, _syncLockCustomers); 

BindingOperations.EnableCollectionSynchronization(Orders <-what should be here ?, _syncLockOrders);
}

}

【问题讨论】:

    标签: c# wpf binding observablecollection


    【解决方案1】:

    将您的订单同步对象移动到您的客户类中,使其成为公共字段,并为您创建的每个客户对象启用同步。

    public class Customer
    {
        public customerID;
        public customerName;
        public object _syncLockOrders = new object();
        .....
        private ObservableCollection<Order> _orderslist;
        public ObservableCollection<Order> orderslist
        {
            get 
            {
                if (_orderslist == null)
                {
                    _orderslist = new ObservableCollection<Order>();
                }
                return _orderslist;
            } 
            private set {_orderslist = value;}}
        }
    }
    
    public class MainWindow : Window
    {
        ...
    
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var firstCustomer = Customers.customerslist.FirstOrDefault();
    
            custDataGrid.DataContext = Customers.customerslist;
            if (firstCustomer != null)
            {
                custDataGrid.SelectedItem = firstCustomer;
                ordersDataGrid.DataContext = firstCustomer.Orders.orderslist;
            } 
     ....
            BindingOperations.EnableCollectionSynchronization(firstCustomer.ordersList, firstCustomer._syncLockOrders);
    }
    

    【讨论】:

    • 如何在非UI类中添加BindingOperations.EnableCollectionSynchronization?它返回一个错误,提示“当前上下文中不存在 BindingOperations”
    • System.Windows.Data 命名空间的 BindingOperations 类部分,因此您需要引用 PresentationFramework.dll。
    • 它似乎不起作用。有了我/以前的解决方案,我至少可以看到整个客户列表——现在,他们也不可见了。还有其他解决方案吗?我还希望将 UI 和操作/数据层分开。
    • 我看到的问题是,如果您尝试为所有客户使用单个静态同步锁定对象,那么对一个客户订单列表的订单集合的任何后台更新都可能会干扰对另一个客户的更新客户的订单列表,因此我建议将其移至 Customer 类。也许我在您的简化示例中遗漏了什么?
    • 我明白你的意思。这说得通。我从您的回答中感觉到,如果我使用 EnableCollectionSynchronization 方法,就没有好的解决方案。使用不同方法的替代解决方案是什么?我希望我的问题(显示收藏集)不是那么独特,以至于没有人成功处理过。
    【解决方案2】:

    请考虑这个:

    // Lock object for synchronization;
    private readonly object _syncLock = new object();
    
    /// <summary>
    /// Initializes a new instance of MainWindow.    
    /// </summary>
    public MainWindow()
    {
        InitializeComponent();
    
        // Sync collection with UI
        BindingOperations.CollectionRegistering += BindingOperations_CollectionRegistering;
    }
    
    /// <summary>
    /// Handles the CollectionRegistering event of the BindingOperations control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="CollectionRegisteringEventArgs"/> instance containing the event data.</param>
    private void BindingOperations_CollectionRegistering(object sender, CollectionRegisteringEventArgs e)
    {
        // Ensure collection exists
        if (Customers == null || Customers.customerslist == null) return;
    
        // Ensure collection is synched with UI
        var myCollection = Customers.customerslist;
        if (!Equals(e.Collection, myCollection)) return;
        BindingOperations.EnableCollectionSynchronization(myCollection, _syncLock);
    }
    

    现在每次有更新时集合都会正确同步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2011-03-30
      相关资源
      最近更新 更多