WPF: Binding commands in styles and/or data templates (MVVM)?
Here's the very quick and simplified explanation of my situation. I have defined a style for Hyperlink
controls and they have Command
property binded to the command defined in a ViewModel
class (simplified):
<Window.Resources>
...
<Style x:Key="hyperlinkStyle" TargetType="Hyperlink">
...
<Setter Property="Command" Value="{Binding Path=OpenHyperlinkCommand}" />
...
</Style>
...
</Window.Resources>
Next, I created a content control in the window I am designing. It has a data template defined, written in the window resources. Inside that data template, I added some hyperlinks and I set those hyperlinks to use the previously defined style.
The window looks like this (simplified):
<Window>
...
<ContentControl
...
ContentTemplate="{StaticResource myDataTemplate}" />
...
</Window>
The data template looks like this (simplified):
<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>
The binding to the OpenHyperlinkCommand
in the style doesn't work because the ViewModel
of the window bound to it contains this command, but the Da开发者_开发问答taTemplate
is bound to the MyType
objects, which do not contain this command (nor should).
How should I make this binding work? Two questions:
Here's my proposal: I named my window
x:Name="myWindow"
, and changed the binding of the command inside the style to this:<Setter Property="Command" Value="{Binding ElementName=myWindow Path=DataContext.OpenHyperlinkCommand}" />
This works, but it looks so dirty. Am I doing this wrong? Is there a better way, more MVVM-like? This is fragile because I am setting specific element name inside a style!
Is it a good practice to write the command bindings inside of a style in the first place? If not, what is the alternative? What if I developed a complex
UserControl
, how would I set commands to components somewhere deep inside its logical tree?
Thanks for all the help!
An alternative syntax would use RelativeSource
<Setter Property="Command" Value="{Binding DataContext.OpenHyperlinkCommand, RelativeSource={Relative Source AncestorType={x:Type Window}}}">
I don't see anything wrong with writing command bindings in a style
精彩评论