绑定在数据模板中的命令在所有 ViewModel 实例中执行
我在 WPF 中的命令和数据模板方面遇到问题,我不知道这是错误还是正常行为。
我有一个包含列表视图的 CustomControl。该控件在多个视图(UserControl 的实例)中使用。控件中包含的列表视图的数据模板是:
<DataTemplate x:Key="StandardContentDisplayDataTemplate">
<Grid d:DesignWidth="193.333" d:DesignHeight="128.036" Margin="25">
<Button Style="{Binding ItemButtonStyle, RelativeSource={RelativeSource AncestorType={x:Type Control:ContentDisplay}}}"
Margin="0"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Center"
Command="{Binding DataContext.ItemTouchCommand, RelativeSource={RelativeSource AncestorType={x:Type Control:ContentDisplay}}}"
CommandParameter="{Binding Id}"
Background="{Binding HexadecimalColor, FallbackValue=#FFAAAA}" BorderThickness="0" HorizontalAlignment="Stretch" Padding="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name, FallbackValue=Mon Item}" HorizontalAlignment="Center" VerticalAlignment="Center" ToolTipService.ToolTip="{Binding Name}" FontSize="14.667" Margin="0" Grid.Row="0"/>
<Image Margin="1,0,1,1" Grid.Row="1" VerticalAlignment="Stretch" Source="{Binding ImageUrl, FallbackValue=/logo.png, TargetNullValue=/logont.png}" Stretch="Uniform" />
</Grid>
</Button>
</Grid>
</DataTemplate>
我所做的是将命令绑定到 ContentDisplay(这是我的 CustomControl)的数据上下文,也就是说,我的 ViewModel。
链接到此命令的操作是导航到包含相同控件的另一个视图,也是其 ViewModel 中的命令,以相同的方式绑定(总共有 3 个级别)。
当我单击顶级视图中的按钮时,它会正确导航到第二级视图,显示其他项目。但是,当实例化 ViewModel 并将 Command 绑定到列表视图中的项目时,该 Command 会被再次调用,一次又一次。 我的理论是,DataTemplate 在绑定命令时通知其所有父级(所有实例)。但也许我的代码中某个地方有错误。
这种行为正常吗?如果是的话,有没有办法以尊重 MVVM 的方式实现我想要实现的目标?
预先感谢您的回复
I have a problem with Commands and Datatemplates in WPF and I don't know if it's a bug or a normal behavior.
I have a CustomControl containing a listview. This control is used in several views (instances of UserControl). The datatemplate of the listview contained in the control is:
<DataTemplate x:Key="StandardContentDisplayDataTemplate">
<Grid d:DesignWidth="193.333" d:DesignHeight="128.036" Margin="25">
<Button Style="{Binding ItemButtonStyle, RelativeSource={RelativeSource AncestorType={x:Type Control:ContentDisplay}}}"
Margin="0"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Center"
Command="{Binding DataContext.ItemTouchCommand, RelativeSource={RelativeSource AncestorType={x:Type Control:ContentDisplay}}}"
CommandParameter="{Binding Id}"
Background="{Binding HexadecimalColor, FallbackValue=#FFAAAA}" BorderThickness="0" HorizontalAlignment="Stretch" Padding="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name, FallbackValue=Mon Item}" HorizontalAlignment="Center" VerticalAlignment="Center" ToolTipService.ToolTip="{Binding Name}" FontSize="14.667" Margin="0" Grid.Row="0"/>
<Image Margin="1,0,1,1" Grid.Row="1" VerticalAlignment="Stretch" Source="{Binding ImageUrl, FallbackValue=/logo.png, TargetNullValue=/logont.png}" Stretch="Uniform" />
</Grid>
</Button>
</Grid>
</DataTemplate>
The thing I do is binding the command to the datacontext of the ContentDisplay (which is my CustomControl) that is to say, my ViewModel.
The action linked to this command is a navigation to another view containing the same control and also a command in its ViewModel, bound the same way (It has a total of 3 levels).
When I click the button in the top level view, it navigates correctly to the 2nd level view, displaying other items. But when the ViewModel is instanciated and the Command bound to the items in the listview, the Command is called once again, and again and again.
My theory is that the DataTemplate notifies all of its parents (all instances) when binding the command. But maybe there is a bug somewhere in my code.
Is this behavior normal? and if it is, is there a way to do what I want to achieve in MVVM-respectful way?
Thank you in advance for your responses
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题就在这里:
您的命令绑定到 ContentDisplay 的 ViewModel。我建议采用您的 DataTemplate 并使用其自己的支持 ViewModel(在该 ViewModel 上使用 ItemTouchCommand)制作 UserControl。公开 UserControl 上的依赖属性,该属性采用正在显示的 Item 的类型。然后您可以更改数据模板以简单地保存该控件的实例,如下所示
The problem is right here:
Your Command is bound to the ContentDisplay's ViewModel. I would recommend taking your DataTemplate and making a UserControl with its own backing ViewModel (with the ItemTouchCommand on that ViewModel). Expose a dependency property on the UserControl that takes the type of the Item that is being displayed. Then you can change your datatemplate to simply hold an instance of that control like so