1

In a WPF Application, I have a ViewModel that is exposing a collection of strings that I'm displaying as buttons through an ItemsControl container using a WrapPanel. I haven't been able to bind the RelayCommand in my ViewModel to the buttons, however.

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 that connects the DataContext

IncidentAddressesTab.DataContext = new IncidentAddressesViewModel();

The buttons are showing with the addresses. When I set a breakpoint at the ZoomToAddressCommand, it does get hit once, but when I click the buttons, the ZoomToAddress method never gets invoked.

UPDATE to include binding details: I am actually binding to the TabItem. I have updated the XAML to include the additional tag and added the binding code in the XAML Code Behind. I didn't know this was pertinent information or I would have added it in the beginning.. (:

4

2 回答 2

5

它不起作用,因为您尝试BindCommandtoItemsControl而不是Button控件。你试过这个吗?:

<DataTemplate>
    <Button Content="{Binding}" Command="{Binding DataContext.ZoomToAddressCommand, 
        RelativeSource={RelativeSource AncestorType={x:Type 
        YourViewNamespace:YourViewName}}}" />
</DataTemplate>

我们在这里尝试做的是BindDataTemplate我假设的视图模型设置为DataContext当前视图的。请将“ YourViewNamespace:YourViewName”替换为您的 XML 命名空间和视图的实际名称。

更新>>>

好的,再次查看您的代码后,我可以看到您只需使用属性名称即可进行集合BindingAddresses你说DataContext设置在 上ItemsControl,所以我假设你的意思是你的视图模型设置在ItemsControl.DataContext属性上。如果是这样,那么我们需要将我们的更改BindingCommand这样的:

<DataTemplate>
    <Button Content="{Binding}" Command="{Binding DataContext.ZoomToAddressCommand, 
        RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
</DataTemplate>

如果您的视图模型未在该ItemsControl.DataContext属性上设置,那么这将不起作用,您需要清楚地告诉我您是如何将您的视图模型连接到您的视图的。在我假设您的视图模型是数据绑定到DataContext包含视图的数据之前,或者Window像通常所做的那样......也许下一次,您可以在您的问题中提供此信息,以便人们更容易回答它?

更新 2 >>>

好的,您已经使用基本DataContext信息更新了问题......完美。现在我可以正确地回答你的问题,而无需所有的猜测......你知道如果你一开始就在那里添加它会容易得多吗?没关系......我们现在在这里。试试这个最后一个例子:

<DataTemplate>
    <Button Content="{Binding}" Command="{Binding DataContext.ZoomToAddressCommand, 
        RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}" />
</DataTemplate>

重申......这RelativeSource Binding将查找可视化树,直到找到TabItem控件。然后,它将查看DataContext该控件的属性。最后,它将ZoomToAddressCommand在对象(您的视图模型)中查找设置为 ... 的属性,DataContext然后TabItem我们就找到了。

于 2013-09-18T13:40:35.970 回答
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>
于 2013-09-18T17:11:46.743 回答