wpf 集合依赖属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15015217/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 07:40:20  来源:igfitidea点击:

collection dependency properties

c#wpfdata-bindingobservablecollectiondependency-properties

提问by user1604008

I have a custom control that has a DependencyPropertyof type ObservableCollectionthat is bound to an observableCollection:

我有一个自定义控件,它DependencyProperty的类型ObservableCollection绑定到observableCollection

<MyControl MyCollectionProperty = {Binding MyObservableCollection} ...

Problem is adding to MyObservableCollectiondoes not update MyCollectionProperty.

问题是添加到MyObservableCollection不更新MyCollectionProperty

I need to completly replace the MyObservableCollectionto make it work e.g.

我需要完全替换MyObservableCollection以使其工作,例如

MyObservableCollection = null;
MyObservableCollection = new ObservableCollection(){...}

Is there a better way to deal with this?

有没有更好的方法来处理这个问题?

EDIT:

编辑:

    public ObservableCollection<string> Columns
    {
        get { return (ObservableCollection<string>)GetValue(ColumnsProperty); }
        set { SetValue(ColumnsProperty, value); }
    }

    public static readonly DependencyProperty ColumnsProperty =
        DependencyProperty.Register("Columns", typeof(ObservableCollection<string>), typeof(MyControl),
                                    new PropertyMetadata(new ObservableCollection<string>(), OnChanged));

回答by Clemens

In addition to what grantz has answered, I would suggest to declare the property with type IEnumerable<string>and check at runtime if the collection object implements the INotifyCollectionChangedinterface. This provides greater flexibility as to which concrete collection implementation may be used as property value. A user may then decide to have their own specialized implementation of an observable collection.

除了grantz 回答的内容之外,我建议使用类型声明属性IEnumerable<string>并在运行时检查集合对象是否实现了INotifyCollectionChanged接口。这为哪些具体的集合实现可以用作属性值提供了更大的灵活性。然后用户可以决定拥有他们自己的可观察集合的专门实现。

Note also that in the ColumnsPropertyChangedcallback the CollectionChangedevent handler is attached to the new collection, but also removed from the old one.

另请注意,在ColumnsPropertyChanged回调中,CollectionChanged事件处理程序附加到新集合,但也从旧集合中删除。

public static readonly DependencyProperty ColumnsProperty =
    DependencyProperty.Register(
        "Columns", typeof(IEnumerable<string>), typeof(MyControl),
        new PropertyMetadata(null, ColumnsPropertyChanged));

public IEnumerable<string> Columns
{
    get { return (IEnumerable<string>)GetValue(ColumnsProperty); }
    set { SetValue(ColumnsProperty, value); }
}

private static void ColumnsPropertyChanged(
    DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    var control= (MyControl)obj;
    var oldCollection = e.OldValue as INotifyCollectionChanged;
    var newCollection = e.NewValue as INotifyCollectionChanged;

    if (oldCollection != null)
    {
        oldCollection.CollectionChanged -= control.ColumnsCollectionChanged;
    }

    if (newCollection != null)
    {
        newCollection.CollectionChanged += control.ColumnsCollectionChanged;
    }

    control.UpdateColumns();
}

private void ColumnsCollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    // optionally take e.Action into account
    UpdateColumns();
}

private void UpdateColumns()
{
    ...
}

回答by grantnz

Below is a working example that may help.

下面是一个可能有帮助的工作示例。

In this example, the method OnChanged is called immediately, when the Add button is clicked "Changed" is written to the console.

在这个例子中,OnChanged 方法被立即调用,当 Add 按钮被点击时,“Changed”被写入控制台。

The Control

控制

public class MyControl : Control
{

    public ObservableCollection<string> ExtraColumns
    {
        get { return (ObservableCollection<string>)GetValue(ExtraColumnsProperty); }
        set { SetValue(ExtraColumnsProperty, value); }
    }

    public static readonly DependencyProperty ExtraColumnsProperty =
        DependencyProperty.Register("ExtraColumns", typeof(ObservableCollection<string>), typeof(MyControl),
                                    new PropertyMetadata(new ObservableCollection<string>(), OnChanged));

    static void OnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        (sender as MyControl).OnChanged();

    }

    void OnChanged()
    {
        if ( ExtraColumns != null )
            ExtraColumns.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ExtraColumns_CollectionChanged);
    }

    void ExtraColumns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        Console.WriteLine("Changed");    
    }
}

The Window

窗户

<Window x:Class="WpfApplication18.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication18"
    Title="MainWindow" Height="350" Width="525">
  <StackPanel>
    <local:MyControl ExtraColumns="{Binding Extras}"/>
    <Button Click="Button_Click">Add</Button>
  </StackPanel>
</Window>

Window Code Behind

窗口代码背后

public partial class MainWindow : Window
{
    private ObservableCollection<string> _extras = new ObservableCollection<string>( );
    public ObservableCollection<string> Extras
    {
        get { return _extras; }
        set
        {
            if (value != _extras)
            {
                _extras = value;
            }
        }
    }


    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Extras.Add("Additional");
    }
}