使用依赖项属性包装属性

时间:2017-05-20 10:52:49

标签: c# wpf mvvm binding dependency-properties

我对MVVM样式项目中外部库中有用的用户控件 Monitor 感兴趣。 一切看起来很好......但是这个控件有简单的(不依赖)只读属性(IList<ILogSource>),我需要填充它。 在思考了一下后,我决定用其他控件 MonitorWrap 包装 Monitor 控件:

<UserControl
    x:Class="Prj.CustomControls.MonitorWrap"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:catel="http://catel.codeplex.com"
    xmlns:uc="clr-namespace:UsefulControll;assembly=UsefulControll">

    <uc:Monitor x:Name="Monitor" />
</UserControl>

在代码后面我创建依赖属性:

public partial class MonitorWrap : UserControl
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MonitorWrap"/> class.
        /// </summary>
        public MonitorWrap()
        {
            InitializeComponent();

            DataContextChanged += (sender, args) =>
            {
                //correct ViewModel sets to DataContext
            };
        }

        public IList<ILogSource> LogSources
        {
            get { return (IList<ILogSource>)GetValue(LogSourcesProperty); }
            set { SetValue(LogSourcesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LogSourcesProperty =
            DependencyProperty.Register("LogSources", typeof(IList<ILogSource>), typeof(MonitorWrap), new PropertyMetadata(null,ChangeCallback));

        private static void ChangeCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var logControlPanelView = d as MonitorWrap;

            //add elements from LogSources to readonly collection property.
        }
    }

父xml的下一步:

<customControls:MonitorWrap LogSources="{Binding Sources}"/>

我希望我会在Change Callback方法中填充集合,但它不起作用。

所以问题:

  1. 我是否正确地填写只读集合?
  2. 怎么了?为什么ChangeCallback方法不起作用。
  3. P.S。 我正在使用MVVM框架并且DataContext设置正确(MonitorWrap构造函数中的lambda表达式工作正常)。

    ViewModel实现INotifyPropertyChanged和代码

    protected override void OnPropertyChanged(AdvancedPropertyChangedEventArgs e)
            {
                base.OnPropertyChanged(e);
                if (e.PropertyName == "Sources")
                {
                    //works fine on property changed
                }
            }
    

    也可以。

1 个答案:

答案 0 :(得分:1)

IList<ILogSource>看起来很可疑,就像你可能会要求更多C#对协方差的支持而不是你会得到的。

viewmodel属性的类型必须可分配给IList<ILogSource>,并且其规则相当严格。

从根本上说,ObservableCollection<ILogSource>IList<ILogSource>,但它不是IList<ILogSource_inherited_Class>。不只是绑定不能做到这一点。您可以将项目从一个复制到另一个,但不能投射。你想要做的只是复制,但类型系统不知道 - 它只是看到你试图做任务。

使用类型IEnumerable<ILogSource>see fiddle)的依赖项属性应该起作用。您需要做的就是将项目复制出来,这样就足够了。如果您需要的只是IList<ILogSource>,请不要告诉编译器您需要IEnumerable<ILogSource>可以执行的所有操作。