[Wpf] تنفيذ التجليد اليدوي توواي ل ListBox.SelectedItems؟


Answers

كنت أبحث عن حل لهذا، ويبدو أن المقترح معقد للغاية. لذلك، هنا هو الحل الجديد طريقين ملزمة التي تقتصر على مجرد الملكية المرفقة، ويستخدم ضعف التعامل مع الحدث لمشاهدة التغييرات في الملكية التبعية محددة. لم أكن أقضي أي وقت في جعل هذا الرصاص، لكنه لا يعمل.

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

لقد كنت تحاول معرفة ما إذا كان هناك طريقة سهلة / ذكية لتنفيذ ملزمة للقائمة ListBox.SelectedItems. إذا كنت قد حاولت نفسك، وسوف تعرف، أن ارتباط الترميز باستخدام بيندينكستنسيون لن تعمل - الخاصية لا يدعم ذلك. لذلك كنت تركت مع الأسلاك حتى معالج ل سيلكتيونشانجد ومحاولة هذا الطريق. أقرب ما حصلت عليه هو هذا المنصب:

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

تحديث: المدونة المذكورة أعلاه لم تعد متوفرة، بلوق المؤلف الحالي هو هنا وأقرب يمكن أن تجد إلى مشاركة بلوق المشار إليها هو هذا ستاكوفيرفلو الجواب .

الذي ينفذ كل ما يلزم C # في الممتلكات المرفقة مفيد. لكنه ينفذ "ملزمة" باعتبارها في اتجاه واحد، الهدف إلى المصدر. أود في اتجاهين ملزمة.

أيه أفكار؟