集合依赖属性

use*_*008 5 c# data-binding wpf dependency-properties observablecollection

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

<MyControl MyCollectionProperty = {Binding MyObservableCollection} ...
Run Code Online (Sandbox Code Playgroud)

问题是添加到MyObservableCollection不更新MyCollectionProperty.

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

MyObservableCollection = null;
MyObservableCollection = new ObservableCollection(){...}
Run Code Online (Sandbox Code Playgroud)

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

编辑:

    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));
Run Code Online (Sandbox Code Playgroud)

Cle*_*ens 14

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

另请注意,在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()
{
    ...
}
Run Code Online (Sandbox Code Playgroud)


gra*_*tnz 6

以下是一个可能有用的工作示例.

在此示例中,立即调用OnChanged方法,单击"添加"按钮时,"已更改"将写入控制台.

控制

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");    
    }
}
Run Code Online (Sandbox Code Playgroud)

窗户

<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>
Run Code Online (Sandbox Code Playgroud)

窗口代码背后

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你不应该在注册依赖属性时使用代码`new PropertyMetadata(new ObservableCollection <string>()`.参见[here](https://msdn.microsoft.com/en-us/library/vstudio/aa970563%28v= vs.100%29.aspx)进行解释 (5认同)