DataTemplate 中的 WPF 命令绑定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24878082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Command binding in DataTemplate
提问by Stacked
I'm using ItemsControlto hold my collection.
The ItemsPanelis a Canvas, the ItemTemplateis a block of Border>StackPanel>TextBlocksI want to bind a command in the DataTemplateto catch the click on a block (item of my collection)
我ItemsControl用来保存我的收藏。的ItemsPanel是Canvas,该ItemTemplate是块Border> StackPanel>TextBlocks我要绑定在一个命令DataTemplate捕获在块上单击(我的收藏项目)
Code:
代码:
<Grid Grid.Row="1" Grid.Column="1" >
<ItemsControl ItemsSource="{Binding Products}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<helpers:DragCanvas
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AllowDragging="True"
AllowDragOutOfView="False" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- The border and its content is what I see
on my canvas, I want to bind a command here (on click do something) -->
<Border BorderThickness="1" BorderBrush="Gold">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Price}" />
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
回答by AymenDaoudi
The first object that comes in mind to be attached to the command is the Borderand since this latter doesn't have a Clickevent, I'm gonna use MouseLeftButtonDown, and since Commands are used only with Button-base controls (Button, RadioButton, CheckBox, RepeatButton ...) you will be needing EventTriggers, your DataTemplate should look like this:
想到要附加到命令的第一个对象是 theBorder并且由于后者没有Click事件,我将使用MouseLeftButtonDown,并且因为 Commands 仅用于Button-base 控件(Button、RadioButton、CheckBox、RepeatButton ...) 您将需要EventTriggers,您的 DataTemplate 应如下所示:
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Gold">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<command:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.MouseLeftButtonDown }"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Price}" />
</StackPanel>
</Border>
</DataTemplate>
Since your ItemsControl's source is bound to Products then, the DataTemplate's DataContext will be a Product object, to avoid that you should bind the command's source to the Window ancestor which its DataContext is bound to the ViewModel that contains the RelayCommand :
由于您的 ItemsControl 的源然后绑定到 Products,DataTemplate 的 DataContext 将是一个 Product 对象,以避免您应该将命令的源绑定到 Window 祖先,它的 DataContext 绑定到包含 RelayCommand 的 ViewModel:
public class MainViewModel : ViewModelBase
{
public class Product
{
public string Name { get; set; }
public string Price { get; set; }
}
public List<Product> Products
{
get
{
return new List<Product>()
{
new Product(){Name = "Product1",Price = "Price1"},
new Product(){Name = "Product2",Price = "Price2"}
};
}
}
public RelayCommand MouseLeftButtonDown { get; set; }
public MainViewModel()
{
MouseLeftButtonDown = new RelayCommand(()=> MessageBox.Show("Message","Hi"));
}
}
PS : The command:EventToCommandis from MVVM-Light ,if you are not using MVVM-Light you can just go using this instead :
PS:command:EventToCommand来自 MVVM-Light,如果您不使用 MVVM-Light,您可以改为使用它:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.MouseLeftButtonDown }" >
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
This should perfectly work, hope I explained well.
这应该完全有效,希望我解释得很好。
回答by Den
You may try something like this:
你可以尝试这样的事情:
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Gold">
<Border.InputBindings>
<MouseBinding MouseAction="LeftClick" Command="{Binding DataContext.SomeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"/>
</Border.InputBindings>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=Price}" />
</StackPanel>
</Border>
</DataTemplate>

