我目前正在创建一个名为UserControlDecoratedComboBox。这是一个带有样式ComboBox的控件,附近带有一些用于实现某些逻辑的按钮。
DecoratedComboBox具有自定义的ItemsSource(类型为List)和其他几个参数,以便在ComboBox中显示此字段或ItemsSource中各项的该字段。 ItemsSourceComboBox绑定(bind)到字段ItemsToShow(类型为List),并且我想同步两个列表,以便ItemsToShow中的项目反射(reflect)ItemsSource中的项目。

目前,我正在这段代码中研究ItemsSource_CollectionChanged事件的机制:

    public IList ItemsToShow
    {
        get { return (IList)GetValue(ItemsToShowProperty); }
        set { SetValue(ItemsToShowProperty, value); }
    }
    public static readonly DependencyProperty ItemsToShowProperty =
        DependencyProperty.Register("ItemsSource", typeof(IList), typeof(DecoratedComboBox),
                    new FrameworkPropertyMetadata(
                                                    null,
                                                    FrameworkPropertyMetadataOptions.AffectsRender
                                                  )
                                    );

    public IList ItemsSource
    {
        get { return (IList)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }
    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IList), typeof(DecoratedComboBox),
                    new FrameworkPropertyMetadata(
                                                    null,
                                                    FrameworkPropertyMetadataOptions.AffectsRender,
                                                    new PropertyChangedCallback(ItemsSourcePropertyChangedCallback)
                                                  )
                                    );
    private static void ItemsSourcePropertyChangedCallback(DependencyObject sender_decorated_combobox, DependencyPropertyChangedEventArgs items_source_changed_args)
    {
        DecoratedComboBox decorated_combobox = sender_decorated_combobox as DecoratedComboBox;
        if decorated_combobox != null)
        {
            decorated_combobox.ItemsSourceChanged(items_source_changed_args.OldValue as INotifyCollectionChanged,
                                                  items_source_changed_args.NewValue as INotifyCollectionChanged);
            decorated_combobox.BuildList();
        }
    }
    private void ItemsSourceChanged(INotifyCollectionChanged old_value, INotifyCollectionChanged new_value)
    {
        if (old_value != null) { old_value.CollectionChanged -= new NotifyCollectionChangedEventHandler(ItemsSource_CollectionChanged); }
        if (new_value != null) { new_value.CollectionChanged += new NotifyCollectionChangedEventHandler(ItemsSource_CollectionChanged); }
    }
    private void ItemsSource_CollectionChanged(object sender_items_source, NotifyCollectionChangedEventArgs args)
    {
        switch (args.Action)
        {
            case NotifyCollectionChangedAction.Add:
        //Insert the items corresponding to args.NewItems at args.NewStartingIndex
                break;
            case NotifyCollectionChangedAction.Move:
        //What to put here?
        //Should I use only args.OldStartingIndex, args.NewStartingIndex?
                break;
            case NotifyCollectionChangedAction.Remove:
        //Remove all the items corresponding to args.OldItems
                break;
            case NotifyCollectionChangedAction.Replace:
        //What to put here?
        //Should I use only args.OldItems, args.NewItems, args.NewStartingIndex?
                break;
            case NotifyCollectionChangedAction.Reset:
        BuildList();
                break;
            default:
                break;
        }
    }
private void BuildList()
{
    //Fully build (again) ItemsToShow
}

在实现自己的逻辑之前,我想知道要放置哪些代码行,而不是“此处放置什么?”。为了使ItemsToShow反射(reflect)ItemsSource的注释?

我已经阅读了(on this blog)关于args的哪些成员(取决于情况)的信息,但是我还没有仔细检查过,因此没有询问。

这里的关键思想是,这段(相当长的)代码将成为一种模式,适用于我需要在我正在构思的任何控件上添加ItemsSource的地方。

在此先感谢您提供任何线索,如有需要,我可以提供更多信息。

最佳答案

您可以监听这些事件,而不必担心实现全新的ItemsSource属性。相反,您可以简单地使用现有的ItemsSource属性。

如果我是您,那么每次发生更改时,我都只是简单地调用BuildList。请参见以下示例:

public class DecoratedComboBox : ComboBox
{
    public IList ItemsToShow
    {
        get { return (IList)GetValue(ItemsToShowProperty); }
        set { SetValue(ItemsToShowProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ItemsToShow.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ItemsToShowProperty =
        DependencyProperty.Register("ItemsToShow", typeof(IList), typeof(DecoratedComboBox), new PropertyMetadata(null));

    static DecoratedComboBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(DecoratedComboBox), new FrameworkPropertyMetadata(typeof(DecoratedComboBox)));
    }

    protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
    {
        base.OnItemsSourceChanged(oldValue, newValue);

        BuildList();
    }

    protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        base.OnItemsChanged(e);

        BuildList();
    }

    private void BuildList()
    {
        //Clear the ItemsToShow List
        ItemsToShow.Clear();

        //TODO: Work out what to put in ItemsToShow
    }
}

关于c# - 将正确的NotifyCollectionChangedEventArgs实现到List成员,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31247509/

10-10 09:44