【问题标题】:TwoWay Manual Binding Implementation for ListBox.SelectedItems?ListBox.SelectedItems 的双向手动绑定实现?
【发布时间】:2010-09-29 16:03:05
【问题描述】:

我一直在尝试查看是否有一种简单/巧妙的方法来实现与 ListBox.SelectedItems 的绑定。如果您自己尝试过,您就会知道,使用 BindingExtension 的标记绑定将不起作用——该属性不支持它。因此,您需要为 SelectionChanged 连接一个处理程序并尝试该路线。我得到的最接近的是这篇文章:

http://alexshed.spaces.live.com/blog/cns!71C72270309CE838!149.entry

更新:上述博客不再可用,该作者当前的博客is here,我能找到的与引用的博客文章最接近的是this StackOverflow answer

它在一个方便的附加属性中实现了所有必要的 C#。但它将“绑定”实现为单向、目标到源。我想要双向绑定。

有什么想法吗?

【问题讨论】:

    标签: wpf data-binding listbox


    【解决方案1】:

    我找到了一个优雅的解决方案,我刚刚抽出时间写了blog post about it

    我所做的是创建一个附加属性 SynchronizedSelectedItems,您可以在 ListBox(实际上是 DataGrid)上设置它。您将它数据绑定到一个集合,然后,通过一点魔术,ListBox 上的 SelectedItems 属性和您的集合保持同步。您可以从我的博文中下载所有代码。

    “魔术”是一个类,它侦听任一集合中的 CollectionChanged 事件,并将更改传播到另一个集合。

    【讨论】:

    • 我尝试将您的源代码用于 Silverlight,但它不起作用。你有 Silverlight 的例子吗?
    • 无法下载示例。您能否在博客文章中分享扩展行为代码或在其他地方分享代码。
    【解决方案2】:

    我一直在为此寻找解决方案,但提议似乎过于复杂。所以,这里有一个新的双向绑定解决方案,它仅限于附加属性,并使用弱事件处理来观察定义的依赖属性的变化。我没有花任何时间做这个防弹,但它确实有效。


    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Windows;
    using System.Windows.Controls;
    
    namespace WpfApplication2
    {
        public class ListBoxHelper
        {
            private static Dictionary<int, bool> SynchToDPInProcessDictionary = new Dictionary<int, bool>();
            private static Dictionary<int, bool> SynchToLBInProcessDictionary = new Dictionary<int, bool>();
    
            public static readonly DependencyProperty SelectedItemsProperty =
                DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), typeof(ListBoxHelper),
                    new FrameworkPropertyMetadata((IList)null,
                        new PropertyChangedCallback(OnSelectedItemsChanged)));
    
            public static IList GetSelectedItems(DependencyObject d)
            {
                return (IList)d.GetValue(SelectedItemsProperty);
            }
    
            public static void SetSelectedItems(DependencyObject d, IList value)
            {
                d.SetValue(SelectedItemsProperty, value);
            }
    
            private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var listBox = d as ListBox;
                if (listBox == null) 
                    throw new InvalidOperationException("ListBoxHelper should only be used with ListBox or ListBox derived classes (like ListView).");
    
                int hashcode = listBox.GetHashCode();
    
                // Gets set on the initial binding.
                if (!SynchToDPInProcessDictionary.ContainsKey(hashcode))
                {
                    SynchToDPInProcessDictionary[hashcode] = false;
                    SynchToLBInProcessDictionary[hashcode] = false;
    
                    var observableCollection = GetSelectedItems(listBox) as INotifyCollectionChanged;
                    if (observableCollection != null)
                    {
                        // Create a weak CollectionChanged event handler on the SelectedItems property
                        // that synchronizes the collection back to the listbox.
                        CollectionChangedEventManager.AddHandler(observableCollection,
                            delegate(object sender, NotifyCollectionChangedEventArgs e2)
                            {
                                SyncToLBSelectedItems(GetSelectedItems(d), (ListBox)d);
                            });
                    }
                }
    
                SynchToDPSelectedItems(listBox);
                listBox.SelectionChanged += delegate
                {
                    SynchToDPSelectedItems(listBox);
                };
            }
    
    
            private static void SynchToDPSelectedItems(ListBox listBox)
            {
                int hashcode = listBox.GetHashCode();
                if (SynchToLBInProcessDictionary[hashcode]) return;
    
                SynchToDPInProcessDictionary[hashcode] = true;
                try
                {
                    IList dpSelectedItems = GetSelectedItems(listBox);
                    dpSelectedItems.Clear();
                    if (listBox.SelectedItems != null)
                    {
                        foreach (var item in listBox.SelectedItems)
                            dpSelectedItems.Add(item);
                    }
                }
                finally
                {
                    SynchToDPInProcessDictionary[hashcode] = false;
                }
            }
    
            private static void SyncToLBSelectedItems(IList dpSelectedItems, ListBox listBox)
            {
                int hashcode = listBox.GetHashCode();
                if (SynchToDPInProcessDictionary[hashcode]) return;
    
                SynchToLBInProcessDictionary[hashcode] = true;
                try
                {
                    listBox.SelectedItems.Clear();
                    if (dpSelectedItems != null)
                    {
                        foreach (var item in dpSelectedItems)
                            listBox.SelectedItems.Add(item);
                    }
                }
                finally
                {
                    SynchToLBInProcessDictionary[hashcode] = false;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-24
      • 2013-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多