假设在WPF中实现了一个简单的MVVM应用程序:
有一个ItemsControl
的视图使用DataTemplate
来解析集合中各种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>
一些基本的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); }
}
}
}
答案 0 :(得分:2)
我会使用常规按钮设置为无UI,并使用ViewModel
CommandParameter
传递给它
例如,
<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
中的每个项目都使用Button进行渲染,Button将执行您指定的任何命令,并将当前ViewModel作为CommandParameter
传递。
在这种情况下,我已指定应覆盖Button.Template
以使用没有用户界面的ContentPresenter
,所以基本上它将是您DataTemplate
的每一个动物是。
如果您有兴趣,还可以在此相关WPF问题上发布其他一些解决方案:What is the best way to simulate a Click, with MouseUp & MouseDown events or otherwise?
答案 1 :(得分:1)
有StackPanel
这个原因的任何原因你还想知道它是Clicked
吗?
我建议您将其更改为Button
并更改Template
,然后将Command
属性连接到ViewModel
中的属性,然后说CommandParamter
1}}作为Type