【问题标题】:Dependency Property: IEnumerable<> working, ICollection<> not working依赖属性:IEnumerable<> 工作,ICollection<> 不工作
【发布时间】:2018-02-22 09:47:53
【问题描述】:

目前我正在构建一个具有依赖属性的自定义控件。这个依赖属性应该是一个对象列表。问题是,当我将依赖属性声明为 IEnumerable&lt;&gt; 时,它会起作用并调用回调方法。但是当我选择ICollection&lt;&gt;IList&lt;&gt; 时,不会调用依赖属性的回调方法。具有依赖属性的自定义控件在自定义控件库中,被我当前的测试项目引用。

我的自定义控件中的依赖属性实现:

private static readonly FrameworkPropertyMetadata depPropMetaData =
    new FrameworkPropertyMetadata(new PropertyChangedCallback(OnStructureChanged));

public static readonly DependencyProperty TreeListStructureProperty =
    DependencyProperty.Register(
        "TreeListStructure",
        typeof(IEnumerable<ITreeListStructure>),
        typeof(TreeListView),
        depPropMetaData);

public IEnumerable<ITreeListStructure> TreeListStructure
{
    get { return (IEnumerable<ITreeListStructure>)this.GetValue(TreeListStructureProperty); }
    set { this.SetValue(TreeListStructureProperty, value); }
}

private static void OnStructureChanged(
    DependencyObject depObj, DependencyPropertyChangedEventArgs eventArgs)
{
    ; //Breakpoint here
}

在我的带有 MainView 窗口的测试项目中,我只需按如下方式绑定 DataContext

TestingWrapperViewModel testingVM = new TestingWrapperViewModel();
testingVM.GenerateTestItems(5);
this.DataContext = testingVM;

为了完成 MainView.xaml 中的绑定:

<TreeListView:TreeListView TreeListStructure="{Binding ViewModelList}">

TestingWrapperViewModel 类只包含以下内容:

class TestingWrapperViewModel : INotifyPropertyChanged
{
    private List<TestingViewModel> _viewModelList = new List<TestingViewModel>();

    public List<TestingViewModel> ViewModelList
    {
        get { return this._viewModelList; }
        set
        {
            this._viewModelList = value;
            OnPropertyChanged("ViewModelList");
        }
    }

    public void GenerateTestItems(uint nAmount)
    {
        //Just generate some objects for testing
    }

    //INotifyPropertyChanged Implemenation
}

TestingViewModel 实现了 ITreeListStructure-Interface:

class TestingViewModel : ITreeListStructure, INotifyPropertyChanged

我刚刚列出的代码会触发 OnStructureChanged 事件并返回 DependencyPropertyChangedEventArgs 中指定数量的元素。但是当我将依赖属性声明中的IEnumerable&lt;&gt; 更改为ICollection&lt;&gt;IList&lt;&gt;List&lt;&gt; 时,根本不会调用回调方法。

我想了解为什么这不起作用。我希望有人能解释一下。

谢谢,

海恩

编辑: 注释格式错误,在此处添加代码:

public void GenerateTestItems(uint nAmount)
    {
        List<TestingViewModel> temp = new List<TestingViewModel>();
        for (uint nCounter = 0; nCounter < nAmount; nCounter++)
        {
            temp.Add(new TestingViewModel("TestObject" + nCounter.ToString()));
        }

        ICollection<ITreeListStructure> test1 = temp; //ERROR
        IEnumerable<ITreeListStructure> test2 = temp;

        this.ViewModelList = temp;
    }

EDIT2:更正了我的 EDIT,以便可以看到错误。

【问题讨论】:

    标签: c# wpf dependency-properties


    【解决方案1】:

    List&lt;TestingViewModel&gt; 类型与ICollection&lt;ITreeListStructure&gt;IList&lt;ITreeListStructure&gt; 的赋值不兼容:

    IEnumerable<ITreeListStructure> x = ViewModelList; // ok
    ICollection<ITreeListStructure> y = ViewModelList; // not ok.
    

    这是因为 IEnumerable&lt;out T&gt; 是协变的,而 ICollection&lt;T&gt; 等不是。

    详情请见this question


    为了访问依赖属性中的集合,你应该使用 LINQ:

    using System.Linq;
    ...
    
    private static void OnStructureChanged(
        DependencyObject depObj, DependencyPropertyChangedEventArgs eventArgs)
    {
        var tls = (IEnumerable<ITreeListStructure>)eventArgs.NewValue;
        var count = tls.Count();
    }
    

    【讨论】:

    • 感谢您的回复,但我还有几个问题。这意味着使用 IEnumerable 的转换是协变的,对吗?是否有可能使用例如ICollection&lt;&gt;-List?从理论上讲,ICollection&lt;&gt; 只需要与&lt;out T&gt; 协变,不是吗?另外,为什么我看到一些使用 ObservableCollection&lt;&gt; 的人的例子对我不起作用?我尝试了你写“ok”和“not ok”的转换,对我来说它有效吗?当我在断点处查看值时,我在两个列表中都有指定数量的元素?
    • 对不起,我不知道。我不知道你看到了什么。当我将属性类型更改为ICollection&lt;ITreeListStructure&gt; 时,根本没有命中断点。将属性声明为IEnumerable&lt;T&gt; 并不意味着在运行时有关实际类型的信息会丢失。运行时(例如在您的调试器中)仍然知道它是 List&lt;TestingViewModel&gt;
    • 我编辑了我的帖子,这样代码就在那里并且格式更好。这就是我在 GenerateTestObjects-method 中的 TestWrapperViewModel 中创建测试对象的地方
    • 啊,忽略这个。我在我的演员阵容中发现了错误。我从TestingViewModel 转换为TestingViewModel,而不是从TestingViewModel 转换为ITreeListStructure。非常感谢您的帮助!!!
    猜你喜欢
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多