wpf - 将 WPF UserControl 绑定(bind)到 View 模型和隐藏代码

标签 wpf mvvm binding viewmodel dependency-properties

我试图了解连接自定义控件以使用依赖项属性和 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/

相关文章:

silverlight - 为 silverlight 应用程序使用 wsHttpBinding 或 basicHttpBinding,哪一个?

wpf - 绑定(bind)到集合是如何真正起作用的?

c# - WPF ItemsControl 不刷新

c# - Wpf - 单独程序集或文件夹中的 MVVM 和服务

.net - 我应该如何从 ViewModel 触发警报?

c# - WPF 更新绑定(bind)到数组中的元素

binding - 了解动态绑定(bind)

c# - 如何在Caliburn.Micro ViewModel中处理WPF MenuItem命令?

c# - MVVM 结构。模型类

c# - 在 C# 中多线程访问 WPF GUI