传播DependencyProperty默认值

时间:2016-05-19 09:13:20

标签: c# wpf mvvm user-controls

我有一个带ViewModel的WPF UserControl:

<MyUserControl ...>
    <Grid Name="UxRootContainer">
        <Grid.DataContext>
            <MyViewModel/>
        </Grid.DataContext>
    </Grid>
</MyUserControl>

                                        

此UserControl具有DependencyProperty,必须传播到ViewModel:

public static readonly DependencyProperty DurationProperty = 
     DependencyProperty.Register( "Duration", typeof(TimeSpan),
     typeof(MyUserControl), new FrameworkPropertyMetadata(TimeSpan.FromHour(1), OnDurationChanged ));

public TimeSpan Duration
{
    get { return (TimeSpan)GetValue(DurationProperty); }
    set { SetValue(DurationProperty, value); }
}

private static void OnDurationChanged(DependencyObject source, 
        DependencyPropertyChangedEventArgs e)
{
    MyUserControl control = source as MyUserControl;
    TimeSpan duration = (TimeSpan)e.NewValue;
    control.UxRootContainer.SetDuration(duration);
}

这项工作正常,但我们不会在OnDurationChanged事件中收到默认值。

我知道我可以在构造函数中自己调用此方法,将默认持续时间设置为常量,但是:

  • 我要为每个DependencyProperty
  • 创建一个常量
  • 即使最后我不使用默认值
  • ,我也必须打电话

关于如何将默认值传播到ViewModel的任何好建议,仅当默认值是最后使用的值时(不是其他值集)。

2 个答案:

答案 0 :(得分:3)

我决定写一个答案(如果我错了,可以看一下投票:)。

在给定的情况下,您正在创建自定义控件,这是一个在其他视图中的简单控件。两点:

  • 不要创建ViewModel;
  • 不要设置此控件的DataContext

在这种情况下,ViewModel不起任何作用:没有要抽象的底层模型,不会重用任何(不是View,也不是ViewModel)。如果没有ViewModel,则默认值已经是依赖属性=问题解决的默认值。

至于DataContext:如果你尝试在列表中使用这个控件将item属性绑定到它,你总是必须通过父容器DataContext来引用它(因为控件有它的覆盖和绑定"{Binding Text}"不会引用该项Text属性,而是引用控件ViewModel Text属性,您将不得不执行"{Binding DataContext.Text, RelativeSource={RelativeSource FindAncestor, AncestorType=Grid}}"之类的操作。这在任何设计中都是不对的。

答案 1 :(得分:1)

  

除了我们不会在OnDurationChanged事件中收到默认值

让班级遵守INotifyPropertyChanged,然后让VM(或任何需要信息的人)订阅该控件的事件。这样当它发生变化时(或者设置了值),就会通知消费者。

请参阅此问题的答案How To Raise Property Changed events on a Dependency Property?

  

关于如何将默认值传播到ViewModel的任何好建议,仅当默认值是最后使用的值时(不是其他值集)。

您描述了需要编码的业务逻辑,以确定是否正在使用默认值。如果没有上述逻辑,您的请求就可以完成。

正在发生的是竞争条件。控件不能绑定通知更改不存在的东西...控件的创建首先发生,默认值设置为秒,然后您的控件绑定到它,所有这些都在运行时。该操作在设计时设置,但这不会影响过程本身。