在WPF应用程序中,我有一个ViewModel,它使用WrapPanel公开我通过ItemsControl容器显示为按钮的字符串集合。但是,我无法将ViewModel中的RelayCommand绑定到按钮上。
ViewModel(IncidentAddressesViewModel):
public IEnumerable<string> Addresses { get; set; }
public RelayCommand<string> ZoomToAddressCommand { get {
if (this.zoomToAddressCommand == null) this.zoomToAddressComamnd = new RelayCommand<string>(this.ZoomToAddress);
return this.zoomToAddressCommand;
}}
private void ZoomToAddress(string address) { MessageBox.Show (address); }
XAML:
<TabItem x:Name="IncidentAddressesTab">
<ItemsControl ItemsSource="{Binding Addresses}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Command">
<cmd:EventToCommand
Command="{Binding ZoomToAddressCommand}"
CommandParameter="{Binding Text}"
PassEventArgsToCommand="True"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</TabItem>
Xaml Code Behind连接DataContext
IncidentAddressesTab.DataContext = new IncidentAddressesViewModel();
按钮显示地址。当我在ZoomToAddressCommand设置断点时,它会被击中一次,但是当我单击按钮时,ZoomToAddress方法永远不会被调用。
更新以包含绑定详细信息: 我实际上绑定到TabItem。我更新了XAML以包含附加标记,并在XAML Code Behind中添加了绑定代码。我不知道这是相关的信息,或者我会在开头添加它..(:
答案 0 :(得分:4)
它不起作用,因为您尝试Bind
Command
到ItemsControl
而不是Button
控件。你试过这个吗?:
<DataTemplate>
<Button Content="{Binding}" Command="{Binding DataContext.ZoomToAddressCommand,
RelativeSource={RelativeSource AncestorType={x:Type
YourViewNamespace:YourViewName}}}" />
</DataTemplate>
我们在这里尝试做的是Bind
从DataTemplate
到我假设的视图模型设置为当前视图的DataContext
。请将“YourViewNamespace:YourViewName
”替换为XML命名空间和视图的实际名称。
更新&gt;&gt;&gt;
好的,在再次查看您的代码后,我可以看到您只是使用属性名称Binding
到Addresses
集合。你说在DataContext
上设置了ItemsControl
,所以我假设你的意思是你的视图模型是在ItemsControl.DataContext
属性上设置的。如果是这样,那么我们需要将Binding
更改为Command
,如下所示:
<DataTemplate>
<Button Content="{Binding}" Command="{Binding DataContext.ZoomToAddressCommand,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
</DataTemplate>
如果您的视图模型未在ItemsControl.DataContext
属性上设置,那么这将无效,您需要清楚地告诉我您是如何将视图模型连接到视图的。在我假设您的视图模型是绑定到包含视图的DataContext
或Window
的数据之前,通常已经完成...也许下次,您可以在您的问题中提供此信息以使其成为可能人们更容易回答它?
更新2&gt;&gt;&gt;
好的,您已经使用必要的DataContext
信息更新了问题...完美。现在我可以在没有猜测的情况下正确回答你的问题...你知道如果你在第一时间添加它会有多容易吗?不管......我们现在在这里。试试这个最后的例子:
<DataTemplate>
<Button Content="{Binding}" Command="{Binding DataContext.ZoomToAddressCommand,
RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}" />
</DataTemplate>
重申......此RelativeSource Binding
将查找可视树,直到找到TabItem
控件。然后,它将查看该控件的DataContext
属性。最后,它会在对象(您的视图模型)中查找ZoomToAddressCommand
属性,该属性设置为DataContext
的{{1}} ......我们就是这样。
答案 1 :(得分:0)
我最终不得不稍微改变结构,
我添加了一个课程:
public class IncidentAddress {
public string Address { get; set; }
private RelayCommand zoomCommand;
public RelayCommand ZoomCommand {
get {
if (zoomCommand == null)
zoomCommand = new RelayCommand(Zoom);
return zoomCommand;
}
}
public void Zoom() {
MessageBox.Show(Address);
}
}
在我的ViewModel中, 这样:
public IEnumerable<string> Addresses { get; set; }
更改为:
public IEnumerable<IncidentAddress> Addresses { get; set; }
我从ViewModel中删除了RelayCommand并将其保留在新类
中XAML最终成了这样:
<TabItem x:Name="IncidentAddressesTab">
<ItemsControl ItemsSource="{Binding Addresses}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Address}" Command="{Binding ZoomCommand}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</TabItem>