相当于Prism ViewModels中的WPF DependencyProperties

时间:2017-09-04 21:26:13

标签: c# wpf xaml mvvm prism

我理解WPF在XAML中公开自定义属性的标准方法是在View的代码隐藏中将其定义为DependencyProperty

但是,这仅适用于DependencyObject,例如UserControl。然而,在干净的Prism方式中,我的代码隐藏(即,派生自UserControl的类)是空的,我处理我的视图模型中的所有逻辑,它来自BindableBase,这是不是DependencyObject的儿童班。

考虑以下XAML片段:

<MyNamespace:MyCustomView MyProperty={Binding} />

MyCustomViewModel的核心是

private string myProperty;
public string MyProperty {
  get { return myProperty; }
  set { SetProperty(ref myProperty, value); }

我对Prism来说还是比较新的。我该怎么做才能公开我MyProperty中定义的MyCustomViewModel,以便我可以在XAML中使用与上述类似的标记进行设置?

更新

按照@ mm8的回答和我们在相应评论中的讨论,我开发了一个关于我的想法的最小(非)工作示例。摘要首先:

  • 数据模型是对象列表。
  • Shell必须通过此对象类型的自定义用户控件显示每个对象。

A)shell

A.1)XAML

XAML很简单。

<Window x:Class="MyProject.Views.MainWindow"
        Name="MainWindowName"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        xmlns:MyNamespace="clr-namespace:MyProject.Views"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525">
  <ItemsControl ItemsSource="{Binding StringCollection, ElementName=MainWindowName}">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <MyNamespace:MyUserControl MyTargetProperty="{Binding}" />
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</Window>

A.2)代码隐藏

代码隐藏包含数据模型定义;实际上,我当然会在Models命名空间中定义它。

using System.Collections;
using System.Windows;

namespace MyProject.Views {
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window {
    public MainWindow() {
      InitializeComponent();

      StringCollection = new ArrayList();
      StringCollection.Add("String 1");
      StringCollection.Add("String 2");
      StringCollection.Add("String 3");
    }

    private ArrayList stringCollection;
    public ArrayList StringCollection {
      get { return stringCollection; }
      set { stringCollection = value; }
    }
  }
}

A.3)查看模型

视图模型是Prism代码模板提供的标准模型。

using Prism.Mvvm;

namespace MyProject.ViewModels {
  public class MainWindowViewModel : BindableBase {
    private string _title = "Prism Unity Application";
    public string Title {
      get { return _title; }
      set { SetProperty(ref _title, value); }
    }

    public MainWindowViewModel() {
    }
  }
}

B)自定义用户控件

这是有趣的开始。最后,我想访问MyTargetProperty中的MyUserControlViewModel,因为我想在其上调用依赖于数据模型的其他工作的复杂程序逻辑,因此不是放在代码隐藏中。

B.1)XAML

很天真;只包含一个标签。

<UserControl x:Class="MyProject.Views.MyUserControl"
             Name="UserControlName"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"             
             prism:ViewModelLocator.AutoWireViewModel="True">
    <Label Content="{Binding MyTargetProperty, ElementName=UserControlName}" Background="AliceBlue"/>
</UserControl>

B.2)代码隐藏

这是我将目标属性声明为DependencyProperty的地方,正如@ mm8的答案所示。

using System.Windows;
using System.Windows.Controls;

namespace MyProject.Views {
  /// <summary>
  /// Interaction logic for MyUserControl
  /// </summary>
  public partial class MyUserControl : UserControl {
    public MyUserControl() {
      InitializeComponent();
    }

    public static readonly DependencyProperty MyTargetPropertyProperty = DependencyProperty.Register("MyTargetProperty", typeof(string), typeof(MyUserControl));
    public string MyTargetProperty {
      get { return (string)GetValue(MyTargetPropertyProperty); }
      set { SetValue(MyTargetPropertyProperty, value); }
    }
  }
}

B.3)查看模型

视图模型定义源属性

using Prism.Mvvm;

namespace MyProject.ViewModels {
  public class MyUserControlViewModel : BindableBase {
    public MyUserControlViewModel() {
    }

    private string mySourceProperty;
    public string MySourceProperty {
      get { return mySourceProperty; }
      set { SetProperty(ref mySourceProperty, value); }
    }
  }
}

我无法终身了解如何访问我在MainWindow视图模型中ItemTemplate的{​​{1}}中设置的值。

1 个答案:

答案 0 :(得分:0)

只有目标(视图)属性必须是依赖项属性。因此,为了能够将任何绑定到这样的属性,在这种情况下它必须是MyProperty之类的依赖属性:

<MyNamespace:MyCustomView MyProperty="{Binding SourceProperty}" />

视图模型中的 source 属性可能是一个普通的CLR属性:

public string SourceProperty { get; set; }

因此,您的视图模型不必(也不应该!)从DependencyObject继承,但视图应该。