[英]WPF Determining DataTemplate object a user clicked on in ItemsControl
Assume a simple MVVM Application implemented in WPF: 假设在WPF中实现了一个简单的MVVM应用程序:
There is a view with an ItemsControl
that uses DataTemplate
s to resolve a view for various ViewModels in a collection. 有一个带有ItemsControl
的视图,该视图使用DataTemplate
来解决集合中各种ViewModel的视图。
What I want to know is, how would I add functionality to allow me to click on a given ViewModel in my ItemsControl
to return that element in the container ViewModel? 我想知道的是,如何添加功能以允许我单击ItemsControl
的给定ViewModel以返回容器ViewModel中的该元素?
That is to say, for the given example, I may want be able to click on my WrapPanel
and then from my BarnYardViewModel
have the particular ViewModel from the ItemSource
tag returned. 也就是说,对于给定的例子,我可能希望能够点击我的WrapPanel
,然后从我的BarnYardViewModel
具有特定视图模型从ItemSource
标签返回。 (much like binding the selected item in a ComboBox
) (很像将选定的项目绑定到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>
And a few basic ViewModels: 还有一些基本的ViewModel:
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); }
}
}
}
I would use a regular Button styled to have no UI, and would pass the ViewModel
to it using the CommandParameter
我将使用样式为没有UI的常规Button,并使用CommandParameter
将ViewModel
传递给它
For example, 例如,
<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>
This will result in each item in your ItemsControl
being rendered using a Button, and the Button will execute whatever command you specify and pass the current ViewModel in as the CommandParameter
. 这将导致使用Button渲染ItemsControl
中的每个项目,并且Button将执行您指定的任何命令,并将当前ViewModel作为CommandParameter
传入。
In this case, I've specified that the Button.Template
should be overwritten to use a ContentPresenter
which has no UI, so basically it will be whatever your DataTemplate
for each animal is. 在这种情况下,我指定应改写Button.Template
以使用没有UI的ContentPresenter
,因此从根本Button.Template
,它将是每种动物的DataTemplate
。
There are some other solutions posted at this related WPF question too if you're interested: What is the best way to simulate a Click, with MouseUp & MouseDown events or otherwise? 如果您有兴趣,也可以在与此相关的WPF问题上发布其他一些解决方案: 用MouseUp和MouseDown事件或其他方式模拟Click的最佳方法是什么?
Any reason why it is a StackPanel
yet you want something to know if it is Clicked
? 它为什么是StackPanel
任何原因,但是您想知道是否Clicked
它?
I suggest you to change it to a Button
and change the Template
for it then hookup the Command
property to a property in your ViewModel
then said the CommandParamter
as the Type
我建议您将其更改为Button
并为其更改Template
,然后将Command
属性连接到ViewModel
的属性,然后将CommandParamter
称为Type
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.