wpf 双向绑定视图的 DependencyProperty 到视图模型的属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15132538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Twoway-bind view's DependencyProperty to viewmodel's property?
提问by l33t
Multiple sources on the net tells us that, in MVVM, communication/synchronization between views and viewmodels should happen through dependency properties. If I understand this correctly, a dependency property of the view should be bound to a property of the viewmodel using two-way binding. Now, similar questions have been asked before, but with no sufficient answer.
网络上的多个来源告诉我们,MVVM视图和视图模型之间的通信/同步应该通过依赖属性发生。如果我理解正确,应该使用双向绑定将视图的依赖属性绑定到视图模型的属性。现在,以前也有人问过类似的问题,但没有足够的答案。
Before I start analyzing this rather complex problem, here's my question:
在我开始分析这个相当复杂的问题之前,这是我的问题:
How do I synchronize a customview's DependencyPropertywith a property of the viewmodel?
如何将自定义视图DependencyProperty与视图模型的属性同步?
In an ideal world, you would simply bind it as this:
在理想的世界中,您只需将其绑定如下:
<UserControl x:Class="MyModule.MyView" MyProperty="{Binding MyProperty}">
That does not work since MyPropertyis not a member of UserControl. Doh! I have tried different approaches, but none proved successful.
这不起作用,因为MyProperty它不是UserControl. 哦!我尝试了不同的方法,但没有一个成功。
One solution is to define a base-class, UserControlEx, with necessary dependency properties to get the above to work. However, this soon becomes extremely messy. Not good enough!
一种解决方案是定义一个基类,UserControlEx,具有必要的依赖属性以使上述工作正常进行。但是,这很快就会变得非常混乱。还不够好!
采纳答案by Michael Schnerring
I use Caliburn.Micro for separating the ViewModel from the View. Still, it might work the same way in MVVM. I guess MVVM sets the view's DataContextproperty to the instance of the ViewModel, either.
我使用 Caliburn.Micro 将 ViewModel 与 View 分开。尽管如此,它可能在 MVVM 中以相同的方式工作。我猜 MVVM 也将视图的DataContext属性设置为 ViewModel 的实例。
VIEW
看法
// in the class of the view: MyView
public string ViewModelString // the property which stays in sync with VM's property
{
get { return (string)GetValue(ViewModelStringProperty); }
set
{
var oldValue = (string) GetValue(ViewModelStringProperty);
if (oldValue != value) SetValue(ViewModelStringProperty, value);
}
}
public static readonly DependencyProperty ViewModelStringProperty =
DependencyProperty.Register(
"ViewModelString",
typeof(string),
typeof(MyView),
new PropertyMetadata(OnStringValueChanged)
);
private static void OnStringValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
// do some custom stuff, if needed
// if not, just pass null instead of a delegate
}
public MyView()
{
InitializeComponent();
// This is the binding, which binds the property of the VM
// to your dep. property.
// My convention is give my property wrapper in the view the same
// name as the property in the VM has.
var nameOfPropertyInVm = "ViewModelString"
var binding = new Binding(nameOfPropertyInVm) { Mode = BindingMode.TwoWay };
this.SetBinding(SearchStringProperty, binding);
}
VM
虚拟机
// in the class of the ViewModel: MyViewModel
public string ViewModelStringProperty { get; set; }
Note, that this kind of implementation lacks completely of implementation of the INotifyPropertyChangedinterface. You'd need to update this code properly.
请注意,这种实现完全缺乏INotifyPropertyChanged接口的实现。您需要正确更新此代码。
回答by Grx70
If you want to do it in XAML, you could try using styles to achieve that.
如果你想在 XAML 中做到这一点,你可以尝试使用样式来实现这一点。
Here's an example:
下面是一个例子:
<UserControl x:Class="MyModule.MyView"
xmlns:local="clr-namespace:MyModule">
<UserControl.Resources>
<Style TargetType="local:MyView">
<Setter Property="MyViewProperty" Value="{Binding MyViewModelProperty, Mode=TwoWay}"/>
</Style>
</UserControl.Resources>
<!-- content -->
</UserControl>
In your case both MyViewPropertyand MyViewModelPropertywould be named MyPropertybut I used different names just to be clear about what is what.
在您的情况下,MyViewProperty和MyViewModelProperty都会被命名,MyProperty但我使用了不同的名称只是为了清楚什么是什么。
回答by somebody
Lets say you have defined your DependencyProperty "DepProp" in the View and want to use the exactly same value in your ViewModel (which implements INotifyPropertyChanged but not DependencyObject). You should be able to do the following in your XAML:
假设您已在视图中定义了 DependencyProperty“DepProp”,并希望在您的 ViewModel(实现 INotifyPropertyChanged 但不实现 DependencyObject)中使用完全相同的值。您应该能够在 XAML 中执行以下操作:
<UserControl x:Class="MyModule.MyView"
xmlns:local="clr-namespace:MyModule"
x:Name="Parent">
<Grid>
<Grid.DataContext>
<local:MyViewModel DepProp="{Binding ElementName=Parent, Path=DepProp}"/>
</Grid.DataContext>
...
</Grid>
</UserControl>

