WPF 确定用户在 ItemsControl 中单击的数据模板对象
本文关键字:数据 对象 单击 用户 ItemsControl WPF | 更新日期: 2023-09-27 17:58:45
假设在WPF中实现一个简单的MVVM应用程序:
有一个视图具有ItemsControl
,该视图使用 DataTemplate
s 解析集合中各种 ViewModel 的视图。
我想知道的是,我将如何添加功能以允许我在ItemsControl
中单击给定的 ViewModel,以在容器 ViewModel 中返回该元素?
也就是说,对于给定的示例,我可能希望能够单击我的WrapPanel
,然后从我的BarnYardViewModel
返回ItemSource
标签中的特定 ViewModel。(很像在ComboBox
中绑定所选项目(
<UserControl x:Class="AGI_ServiceTool.View.DataMonitorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:vm="clr-namespace:MyProject.ViewModel">
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:MooCowViewModel}">
<StackPanel>
<Image Source="/View/Images/MooCow.png"/>
<label content="This is a Moo Cow"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ChickenViewModel}">
<StackPanel>
<Image Source="/View/Images/Chicken.png"/>
<label content="This is a Chicken"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:HorseViewModel}">
<StackPanel>
<Image Source="/View/Images/SarahJessicaParker.png"/>
<label content="This is a Horse"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding MyAnimals}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" ScrollViewer.CanContentScroll="True" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</UserControl>
以及一些基本的视图模型:
namespace MyProject.ViewModel
{
class AbstractViewModel : INotifyPropertyChanged { ... }
class MooCowViewModel : AbstractViewModel {}
class ChickenViewModel : AbstractViewModel {}
class HorseViewModel : AbstractViewModel {}
class BarnYardViewModel : AbstractViewModel
{
public BarnYardViewModel()
{
_myAnimals.add(new MooCowViewModel());
_myAnimals.add(new ChickenViewModel());
_myAnimals.add(new HorseViewModel());
}
private ObservableCollection<AbstractViewModel> _myAnimals = new ObservableCollection<AbstractViewModel>();
public ICollectionView MyAnimals{
get { return System.Windows.Data.CollectionViewSource.GetDefaultView(_myAnimals); }
}
}
}
我会使用一个没有UI的常规按钮,并使用CommandParameter
将ViewModel
传递给它
例如
<ControlTemplate x:Key="ContentOnlyTemplate" TargetType="{x:Type Button}">
<ContentPresenter />
</ControlTemplate>
...
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding ElementName=MyItemsControl, Path=DataContext.MyClickCommand}"
CommandParameter="{Binding }"
Template="{StaticResource ContentOnlyTemplate}"
Content="{Binding }" />
</ItemsPanelTemplate>
</ItemsControl.ItemTemplate>
这将导致ItemsControl
中的每个项目都使用按钮进行渲染,并且按钮将执行您指定的任何命令,并将当前 ViewModel 作为CommandParameter
传入。
在这种情况下,我指定应覆盖Button.Template
以使用没有 UI 的ContentPresenter
,因此基本上它将是您对每种动物的DataTemplate
。
如果您有兴趣,在这个相关的 WPF 问题中也发布了一些其他解决方案:模拟单击、MouseUp 和 MouseDown 事件或其他方式的最佳方法是什么?
为什么
它是一个StackPanel
但你想知道它是否Clicked
?
我建议您将其更改为Button
并更改其Template
,然后将Command
属性连接到ViewModel
中的属性,然后将CommandParamter
称为Type