将命令绑定到列表

时间:2009-10-08 22:29:08

标签: wpf data-binding viewmodel

我有一个相同的命令,我想用于对话框类型窗口上的两个控件。作为潜在的有趣背景,我正在使用Josh Smith的ViewModel / RelayCommand想法,因为我是WPF的新手,这是我见过的第一件事我可以从大图的角度理解。

因此该命令是ViewModel的一个属性,并且使用Button的内置支持,绑定到XAML中的命令是微不足道的:

<Button ... Command="{Binding Path=PickCommand}"  Content="_Ok"></Button>

现在在ListView中,我使用相同的命令连接双击时触发的唯一方法是使用事件处理程序:

<ListView ...
              ItemsSource="{Binding Path=AvailableProjects}" 
              SelectedItem="{Binding Path=SelectedProject, Mode=TwoWay}"
              MouseDoubleClick="OnProjectListingMouseDoubleClick"
              >

private void OnProjectListingMouseDoubleClick(object sender, MouseButtonEventArgs e) {
        var vm = (ProjectSelectionViewModel) DataContext;
        vm.Pick(); // execute the pick command
    }

有没有办法通过绑定按钮的方式来做到这一点?

干杯,
Berryl

&lt; -------实施 - 有更好的方法吗? ---&GT;

您的SelctionBehavior课程已经确定,但我对您的xaml代码感到困惑。通过在listViewItem上设置“Style”,我得到了DataContext的子节点,我想在其中执行命令。所以我将行为附加到ListView本身:

<ListView ...Style="{StaticResource _attachedPickCommand}" >

将样式放在资源字典中:

<Style x:Key="_attachedPickCommand" TargetType="ListView">
    <Setter Property="behaviors:SelectionBehavior.DoubleClickCommand" Value="{Binding Path=PickCommand}" />
</Style>

有效!但是设置列表视图的样式属性“感觉”很尴尬。这只是因为我对wpf中的视觉效果不是很满意,还是有更好的方法呢?

干杯,谢谢! Berryl

1 个答案:

答案 0 :(得分:1)

是的!您可以使用附加的行为并将命令绑​​定到该行为。

  public class SelectionBehavior {
public static readonly DependencyProperty CommandParameterProperty=
  DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(SelectionBehavior));

public static readonly DependencyProperty DoubleClickCommandProperty=
  DependencyProperty.RegisterAttached("DoubleClickCommand", typeof(ICommand), typeof(SelectionBehavior),
                                      new PropertyMetadata(OnDoubleClickAttached));

private static void OnDoubleClickAttached(DependencyObject d, DependencyPropertyChangedEventArgs e) {
  var fe=(FrameworkElement)d;

  if(e.NewValue!=null && e.OldValue==null) {
    fe.PreviewMouseDown+=fe_MouseDown;
  } else if(e.NewValue==null && e.OldValue!=null) {
    fe.PreviewMouseDown-=fe_MouseDown;
  }
}

private static void fe_MouseDown(object sender, MouseButtonEventArgs e) {
  if(e.ClickCount==2) {
    var dep=(FrameworkElement)sender;

    var command=GetDoubleClickCommand(dep);

    if(command!=null) {
      var param=GetCommandParameter(dep);
      command.Execute(param);
    }
  }
}

public static ICommand GetDoubleClickCommand(FrameworkElement element) {
  return (ICommand)element.GetValue(DoubleClickCommandProperty);
}

public static void SetDoubleClickCommand(FrameworkElement element, ICommand value) {
  element.SetValue(DoubleClickCommandProperty, value);
}

public static object GetCommandParameter(DependencyObject element) {
  return element.GetValue(CommandParameterProperty);
}

public static void SetCommandParameter(DependencyObject element, object value) {
  element.SetValue(CommandParameterProperty, value);
}

}

并且在xaml中,您需要为ListViewItem设置一个样式,该样式表示ListView中的数据。实施例

        <ListView>
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="local:SelectionBehavior.DoubleClickCommand" Value="{Binding Path=DataContext.PickCommand}"/>
                <Setter Property="local:SelectionBehavior.CommandParameter" Value="{Binding Path=DataContext}"/>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

以下是有关Attached Behavior pattern

的更多信息