我试图了解连接自定义控件以使用依赖项属性和 View 模型的最佳方法。实现依赖属性来公开可在 XAML 中使用的属性来初始化 View 模型中的属性。例如,在自定义控件的代码隐藏中,我可以定义以下依赖属性:
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register(
"MyProperty", typeof(string), typeof(MyControl), new PropertyMetadata(null));
public string MyProperty
{
get { return (string)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
其中 View 模型定义为
public class MyControlViewModel : INotifyPropertyChanged
{
public MyControlViewModel()
{
_myProperty = "Default View Model string";
}
private string _myProperty;
public string MyProperty
{
get
{
return _myProperty;
}
set
{
_myProperty = value;
OnPropertyChanged("MyProperty");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
自定义控件绑定(bind)到 View 模型 MyProperty,如下所示
<UserControl x:Class="MyProject.MyControlView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyProject">
<UserControl.DataContext>
<local:MyControlViewModel/>
</UserControl.DataContext>
<Grid>
<TextBlock Text="{Binding MyProperty}"/>
</Grid>
</UserControl>
现在,由于我已经在自定义控件的代码后面定义了依赖属性 MyProperty,所以我希望能够使用它来初始化 ViewModel 中的 MyProperty。所以像这样
<Window x:Class="MyProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyProject"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:MyControlView MyProperty="This was set in XAML"/>
</Grid>
</Window>
运行上述命令将显示在 View 模型构造函数中设置的字符串“默认 View 模型字符串”。如何连接依赖属性值,以便它正确初始化 View 模型中的字符串?即它应该显示“This was set in XAML”。
更新
我可以在后面的代码中设置属性更改回调,并在 View 模型中设置值,即
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(string), typeof(MyControlView), new PropertyMetadata("Default", OnMyPropertyChanged));
private static void OnMyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var view = d as MyControlView;
if (view != null)
{
var viewModel = view.DataContext as MyControlViewModel;
if (viewModel != null)
{
viewModel.MyProperty = e.NewValue as string;
}
}
}
这是正确的还是有味道?
最佳答案
您已经创建了很好的依赖属性。但是,您通过实例化 View 模型并将其属性使用到后面的代码中来实现紧密耦合。这是错误的方式。
您应该从“Control
”继承您的类并用于绑定(bind)值,并创建一个DP
,如下所示在自定义控件类
中:
public static readonly DependencyProperty myValueProperty = DependencyProperty.Register(
"MyProperty", typeof(object), typeof(FieldControl), new FrameworkPropertyMetadata(null, myValueChanged));
那么,
private static void myValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var fc = dependencyObject as FieldControl;
if (fc != null)
{
fc.SetValue(BindingExpression1Key, fc.GetBindingExpression(ValueProperty));
fc.RaiseValueChangedEvent(dependencyPropertyChangedEventArgs);
}
}
现在,使用它并绑定(bind)您的属性,如下所示:
<local:MyControlView MyProperty="{Binding MyProperty, Mode=TwoWay}"/>
关于wpf - 将 WPF UserControl 绑定(bind)到 View 模型和隐藏代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31047284/