WPF: Связывание команд в стилях и / или шаблонах данных (MVVM)? - PullRequest
8 голосов
/ 13 апреля 2011

Вот очень быстрое и упрощенное объяснение моей ситуации. Я определил стиль для Hyperlink элементов управления, и у них есть свойство Command, связанное с командой, определенной в классе ViewModel (упрощенно):

<Window.Resources>
  ...
  <Style x:Key="hyperlinkStyle" TargetType="Hyperlink">
    ...
    <Setter Property="Command" Value="{Binding Path=OpenHyperlinkCommand}" />
    ...
  </Style>
  ...
</Window.Resources>

Затем я создал элемент управления контентом в окне, которое я проектирую. Для него определен шаблон данных, записанный в окне ресурсов. Внутри этого шаблона данных я добавил несколько гиперссылок и настроил эти гиперссылки на использование ранее определенного стиля.

Окно выглядит так (упрощенно):

<Window>
  ...
  <ContentControl 
      ...
      ContentTemplate="{StaticResource myDataTemplate}" />
  ...
</Window>

Шаблон данных выглядит следующим образом (упрощенно):

<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>

Привязка к OpenHyperlinkCommand в стиле не работает, поскольку ViewModel привязанного к нему окна содержит эту команду, но DataTemplate привязан к объектам MyType, которые не содержат эта команда (и не должна).

Как мне заставить эту привязку работать? Два вопроса:

  1. Вот мое предложение: я назвал свое окно x:Name="myWindow" и изменил привязку команда внутри стиля к этому:

    <Setter Property="Command" Value="{Binding ElementName=myWindow Path=DataContext.OpenHyperlinkCommand}" />
    

    Это работает, но выглядит так грязно. Я делаю это неправильно? Есть ли лучший способ, больше MVVM-как? Это хрупко, потому что я задаю конкретное имя элемента в стиле!

  2. Это хорошая практика - писать привязки команд внутри стиля в первом место? Если нет, какова альтернатива? Что если я разработал комплекс UserControl, Как бы я установить команды для компонентов где-то глубоко внутри его логического дерева?

Спасибо за помощь!

1 Ответ

19 голосов
/ 13 апреля 2011
  1. Альтернативный синтаксис будет использовать RelativeSource

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

  2. Я не вижу ничего плохого в написании привязок команд в стиле

...