WPF:样式和/或数据模板(MVVM)中的绑定命令?

Bor*_*ris 9 wpf binding styles mvvm

这是我的情况的非常快速和简化的解释.我已经为Hyperlink控件定义了一个样式,它们具有Command绑定到ViewModel类(简化)中定义的命令的属性:

<Window.Resources>
  ...
  <Style x:Key="hyperlinkStyle" TargetType="Hyperlink">
    ...
    <Setter Property="Command" Value="{Binding Path=OpenHyperlinkCommand}" />
    ...
  </Style>
  ...
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

接下来,我在我正在设计的窗口中创建了一个内容控件.它有一个定义的数据模板,写在窗口资源中.在该数据模板中,我添加了一些超链接,并设置了这些超链接以使用先前定义的样式.

窗口看起来像这样(简化):

<Window>
  ...
  <ContentControl 
      ...
      ContentTemplate="{StaticResource myDataTemplate}" />
  ...
</Window>
Run Code Online (Sandbox Code Playgroud)

数据模板看起来像这样(简化):

<Window.Resources>
  ...
  <DataTemplate x:Key="myDataTemplate DataType="{x:Type my:MyType}">
    ...
    <TextBlock>
      <Hyperlink 
          Style="{StaticResource hyperlinkStyle}" 
          CommandParameter="{Binding Path=Uri1}">
        <TextBlock Text="{Binding Path=Uri1}" />
      </Hyperlink>
    </TextBlock>
    ...
    <TextBlock>
      <Hyperlink 
          Style="{StaticResource hyperlinkStyle}" 
          CommandParameter="{Binding Path=Uri2}">
        <TextBlock Text="{Binding Path=Uri2}" />
      </Hyperlink>
    </TextBlock>
    ...
  </DataTemplate>
  ...
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

OpenHyperlinkCommand对样式中的绑定不起作用,因为ViewModel绑定到它的窗口包含此命令,但DataTemplate绑定到MyType不包含此命令的对象(也不应该).

我应该如何使这个绑定工作?两个问题:

  1. 这是我的建议:我命名了我的窗口x:Name="myWindow",并将样式内的命令绑定更改为:

    <Setter Property="Command" Value="{Binding ElementName=myWindow Path=DataContext.OpenHyperlinkCommand}" />
    
    Run Code Online (Sandbox Code Playgroud)

    这有效,但看起来很脏.我做错了吗?有更好的方法,更像MVVM吗?这很脆弱,因为我在一个样式中设置特定的元素名称!

  2. 首先在样式中编写命令绑定是一个好习惯吗?如果没有,有什么替代方案?如果我开发了一个复合体UserControl怎么办?如何在逻辑树内部的某个位置设置命令呢?

感谢您的帮助!

Rac*_*hel 20

  1. 另一种语法是使用RelativeSource

    <Setter Property="Command" Value="{Binding DataContext.OpenHyperlinkCommand, RelativeSource={Relative Source AncestorType={x:Type Window}}}">

  2. 我没有看到在一个样式中编写命令绑定有什么问题