2013-07-02 60 views
17

我有一個Datagrid,並且不喜歡我的解決方法在點擊(又名選定)行的viewmodel上觸發雙擊命令。將DoubleClick命令從DataGrid行綁定到虛擬機

查看:

<DataGrid EnableRowVirtualization="True" 
       ItemsSource="{Binding SearchItems}" 
       SelectedItem="{Binding SelectedItem}" 
       SelectionMode="Single" 
       SelectionUnit="FullRow"> 

     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="MouseDoubleClick"> 
       <cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}" PassEventArgsToCommand="True" /> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
     ... 
    </DataGrid> 

視圖模型:

public ICommand MouseDoubleClickCommand 
    { 
     get 
     { 
      if (mouseDoubleClickCommand == null) 
      { 
       mouseDoubleClickCommand = new RelayCommand<MouseButtonEventArgs>(
        args => 
        { 
         var sender = args.OriginalSource as DependencyObject; 
         if (sender == null) 
         { 
          return; 
         } 
         var ancestor = VisualTreeHelpers.FindAncestor<DataGridRow>(sender); 
         if (ancestor != null) 
         { 
          MessengerInstance.Send(new FindDetailsMessage(this, SelectedItem.Name, false)); 
         } 
        } 
        ); 
      } 
      return mouseDoubleClickCommand; 
     } 
    } 

我想在我的視圖模型擺脫視圖相關的代碼(具有依賴對象和可視樹幫手)的,因爲這會以某種方式破壞可測試性。但另一方面,這種方式避免了當用戶沒有點擊某行而是在標題上時發生了某些事情。 PS:我試着看看附加的行爲,但我無法在工作中從Skydrive下載,所以'內置'解決方案將是最好的。

回答

23

爲什麼不簡單使用CommandParameter

<DataGrid x:Name="myGrd" 
      ItemsSource="{Binding SearchItems}" 
      SelectedItem="{Binding SelectedItem}" 
      SelectionMode="Single" 
      SelectionUnit="FullRow"> 

    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseDoubleClick"> 
      <cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}" 
           CommandParameter="{Binding ElementName=myGrd, Path=SelectedItem}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
    ... 
</DataGrid> 

你的命令是這樣的:

public ICommand MouseDoubleClickCommand 
{ 
    get 
    { 
     if (mouseDoubleClickCommand == null) 
     { 
      mouseDoubleClickCommand = new RelayCommand<SearchItem>(
       item => 
       { 
        var selectedItem = item; 
       }); 
     } 

     return mouseDoubleClickCommand; 
    } 
} 

編輯:我現在改用此的Interaction.Triggers

<DataGrid.InputBindings> 
    <MouseBinding MouseAction="LeftDoubleClick" 
        Command="{Binding Path=MouseDoubleClickCommand}" 
        CommandParameter="{Binding ElementName=myGrd, Path=SelectedItem}" /> 
</DataGrid.InputBindings> 
+1

問題是沒有得到所選項目(這是數據綁定無論如何在虛擬機上),但是當例如數據網格的頭部被雙擊時得到命令不執行。 – metacircle

+2

如果你想防止mousedoubleclick你可以嘗試PreviewMouseDoubleClick併爲您的條件設置e.Handled = true。所以你可以從viewmodel中取代代碼並將它放在你的數據網格的代碼隱藏文件中 – blindmeis

+0

好主意。其實我一直在爲我的代碼隱藏OnContextMenuOpening一直做同樣的事情。有時候,你只是在正確的時間沒有正確的想法。謝謝。我打算將此標記爲答案。 – metacircle

0

您可以嘗試以下解決方法:

<DataGrid EnableRowVirtualization="True" 
      ItemsSource="{Binding SearchItems}" 
      SelectedItem="{Binding SelectedItem}" 
      SelectionMode="Single" 
      SelectionUnit="FullRow"> 
    <DataGrid.Columns> 
     <DataGridTemplateColumn Header="....."> 
      <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
         <TextBlock .....> 
          <i:Interaction.Triggers> 
           <i:EventTrigger EventName="MouseDoubleClick"> 
            <cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}" PassEventArgsToCommand="True" /> 
           </i:EventTrigger> 
          </i:Interaction.Triggers> 
         </TextBlock> 
       </DataTemplate> 
    ................... 

在這種情況下,你必須在DataGrid

+0

我想這會工作,但如果我有這個,我的解決方法之間做出選擇,我可能會與我的堅持。如果我更改列,我總是必須爲每列重複您的XAML代碼。 – metacircle

11

這裏每列指定DataTemplate是你可以如何使用附加的行爲實現:

編輯:現在在DataGridRow而不是DataGrid上註冊行爲,以便點擊DataGridHeader點擊或。

行爲:

public class Behaviours 
{ 
    public static DependencyProperty DoubleClickCommandProperty = 
     DependencyProperty.RegisterAttached("DoubleClickCommand", typeof(ICommand), typeof(Behaviours), 
              new PropertyMetadata(DoubleClick_PropertyChanged)); 

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

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

    private static void DoubleClick_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var row = d as DataGridRow; 
     if (row == null) return; 

     if (e.NewValue != null) 
     { 
      row.AddHandler(DataGridRow.MouseDoubleClickEvent, new RoutedEventHandler(DataGrid_MouseDoubleClick)); 
     } 
     else 
     { 
      row.RemoveHandler(DataGridRow.MouseDoubleClickEvent, new RoutedEventHandler(DataGrid_MouseDoubleClick)); 
     } 
    } 

    private static void DataGrid_MouseDoubleClick(object sender, RoutedEventArgs e) 
    { 
     var row= sender as DataGridRow; 

     if (row!= null) 
     { 
      var cmd = GetDoubleClickCommand(row); 
      if (cmd.CanExecute(row.Item)) 
       cmd.Execute(row.Item); 
     } 
    } 
} 

的XAML:

<DataGrid x:Name="grid" EnableRowVirtualization="True" 
      SelectedItem="{Binding SelectedItem}" 
      SelectionMode="Single" 
      SelectionUnit="FullRow" ItemsSource="{Binding SearchItems}"> 
     <DataGrid.RowStyle> 
      <Style TargetType="DataGridRow"> 
       <Setter Property="Behaviours.DoubleClickCommand" Value="{Binding ElementName=grid, Path=DataContext.SortStateCommand}"/> 
      </Style> 
     </DataGrid.RowStyle> 

然後,您將需要修改MouseDoubleClickCommand刪除MouseButtonEventArgs參數,並與您的SelectedItem類型更換它。

+0

我喜歡這是一個近乎完美的解決方案。因此,這是所附加事件的意思: http://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF – James

7

的方式比任何這裏所提出的解決方案的簡單。

我正在使用這一個。

<!-- 
requires IsSynchronizedWithCurrentItem 
for more info on virtualization/perf https://stackoverflow.com/questions/9949358/datagrid-row-virtualization-display-issue 
--> 
     <DataGrid ItemsSource="{Binding SearchItems}" 
        IsSynchronizedWithCurrentItem="True" 
        AutoGenerateColumns="false" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" EnableRowVirtualization="True" 
        > 

      <!-- for details on ICollection view (the magic behind {Binding Accounts/} https://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/ --> 

      <DataGrid.InputBindings> 
       <MouseBinding 
        MouseAction="LeftDoubleClick" 
        Command="{Binding MouseDoubleClickCommand}" 
        CommandParameter="{Binding SearchItems/}" /> 
      </DataGrid.InputBindings> 
     </DataGrid> 

WPF DataGrid: CommandBinding to a double click instead of using Events

+0

謝謝你的初始鏈接源 - 它很有用。對於閱讀此評論的其他人:請特別注意CommandParameter屬性值(即「SearchItems /」)結尾的正斜槓。 –

相關問題