我有一个带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 回答
让该类遵循
INotifyPropertyChanged
然后让VM(或任何需要该信息)订阅该控件的事件 . 这样当它发生变化时(或者设置了值),就会通知消费者 .看到这个回答这个问题How To Raise Property Changed events on a Dependency Property?
您描述了需要编码的业务逻辑,以确定是否正在使用默认值 . 如果没有上述逻辑,您的请求就可以完成 .
发生的事情是竞争条件 . 控件不能绑定通知更改不存在的东西...控件的创建首先发生,默认值设置为秒,然后您的控件绑定到它,所有这些都在运行时 . 操作在设计时设置,但这不会影响过程本身 .
我决定写一个答案(看看我错了:) .
在给定的情况下,您正在创建自定义控件,这意味着在其他视图中是一个简单的控件 . 两点:
不创建ViewModel;
不设置此控件的
DataContext
.在这种情况下,ViewModel不起任何作用:没有要抽象的底层模型,任何(不是View,也不是ViewModel)都将被重用 . 如果没有ViewModel,则默认值已经是依赖属性=问题解决的默认值 .
至于
DataContext
:如果您尝试在列表中使用此控件将项属性绑定到它,您将始终必须通过父容器DataContext
引用它(因为控件具有其覆盖并且绑定"{Binding Text}"
将不会引用该项Text
属性,但是控制ViewModel Text属性,你必须做"{Binding DataContext.Text, RelativeSource={RelativeSource FindAncestor, AncestorType=Grid}}"
这样的事情 . 这在任何设计中都是不对的 .