2009-10-16 164 views
9

我正在使用WPF Toolkit的DataGrid。我已經啓用了DataGrid上的屬性以允許多行選擇。我如何獲得SelectedItems?我正在使用MVVM框架將我的ViewModel綁定到我的視圖。WPF Toolkit DataGrid多選:如何獲取SelectedItems?

謝謝!

+0

通過http://stackoverflow.com/a/2615487/284795 – 2012-11-21 14:49:23

回答

4

我一直在尋找這個問題的答案。我找到的答案是

1)在代碼隱藏中將工作委託給ViewModel中的方法,從DataGrid傳遞SelectedItems列表。該集合將包含所選的所有項目。

或者

2)使用MVVM工具包光,使您可以使用事件來指揮並直接傳遞一個對象作爲參數傳遞給視圖模型。

private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    IList lst = this.myDataGrid.SelectedItems; 
    ViewModel.RowsSelected(lst); 
} 

在這種情況下,你需要綁定你在你的XAML SelectionChangedselectionchanged在後面的代碼。然後在你的代碼後面,你可以保存這個列表,並用它來刪除選定的行等。

如果有更好的方法來做到這一點,我很想知道是否是好的。

HTH

比爾

2

我設法使用命令中繼比爾提到的來解決這個問題。這部分內容有點骯髒,但我避免將任何代碼放在後面的文件中。首先,在你的XAML中 - 將你的命令綁定到一個按鈕上,或者任何觸發你的RelayCommand的東西。

<Button Content="Select" 
     cmd:ButtonBaseExtensions.Command="{Binding CommandSelect}" 
     cmd:ButtonBaseExtensions.CommandParameter="{Binding ElementName=Results, Path=SelectedItems}" /> 

您會注意到命令參數綁定到另一個UI元素 - 您希望獲得所選項目的DataGrid或ListView。此語法將在Silverlight 3以及WPF中起作用,因爲它現在支持元素到元素的綁定。

在您的視圖模型的命令會是這個樣子

Private _CommandSelect As RelayCommand(Of IEnumerable) 

Public ReadOnly Property CommandSelect() As RelayCommand(Of IEnumerable) 
    Get 
     If _CommandSelect Is Nothing Then 
      _CommandSelect = New RelayCommand(Of IEnumerable)(AddressOf CommandSelectExecuted, AddressOf CommandSelectCanExecute) 
     End If 
     Return _CommandSelect 
    End Get 
End Property 


Private Function CommandSelectExecuted(ByVal parameter As IEnumerable) As Boolean 

    For Each Item As IElectoralAreaNode In parameter 

    Next 

    Return True 
End Function 

Private Function CommandSelectCanExecute() As Boolean 
    Return True 
End Function 

選定的項目將返回一個SelectedItemCollection,但你可能不希望此扶養您的視圖模型。因此,將它作爲IEnumerable鍵入並做一點點投射是你唯一的選擇,而不是「骯髒」。但它使您的代碼保持清潔和MVVM模式!

6

考慮到比爾的答案,合併選項1和2,添加一個附加屬性作爲替代書寫代碼隱藏的泛濫,我想出了一個行爲。

首先,我們具有以下行爲:

Public Class SelectedItemsBehavior 

    Public Shared ReadOnly SelectedItemsChangedHandlerProperty As DependencyProperty = 
     DependencyProperty.RegisterAttached("SelectedItemsChangedHandler", 
      GetType(mvvm.RelayCommand), GetType(SelectedItemsBehavior), 
      New FrameworkPropertyMetadata(New PropertyChangedCallback(AddressOf OnSelectedItemsChangedHandlerChanged))) 




    Public Shared Function GetSelectedItemsChangedHandler(ByVal element As DependencyObject) As mvvm.RelayCommand 
     If element Is Nothing Then Throw New ArgumentNullException("element") 
     Return element.GetValue(SelectedItemsChangedHandlerProperty) 
    End Function 

    Public Shared Sub SetSelectedItemsChangedHandler(ByVal element As DependencyObject, ByVal value As mvvm.RelayCommand) 
     If element Is Nothing Then Throw New ArgumentNullException("element") 
     element.SetValue(SelectedItemsChangedHandlerProperty, value) 
    End Sub 

    Private Shared Sub OnSelectedItemsChangedHandlerChanged(d As DependencyObject, 
                  e As DependencyPropertyChangedEventArgs) 

     Dim dataGrid As DataGrid = DirectCast(d, DataGrid) 

     If e.OldValue Is Nothing AndAlso e.NewValue IsNot Nothing Then 
      AddHandler dataGrid.SelectionChanged, AddressOf ItemsControl_SelectionChanged 
     End If 

     If e.OldValue IsNot Nothing AndAlso e.NewValue Is Nothing Then 
      RemoveHandler dataGrid.SelectionChanged, AddressOf ItemsControl_SelectionChanged 
     End If 

    End Sub 


    Public Shared Sub ItemsControl_SelectionChanged(sender As Object, 
                e As SelectionChangedEventArgs) 

     Dim dataGrid As DataGrid = DirectCast(sender, DataGrid) 

     Dim itemsChangedHandler As RelayCommand = GetSelectedItemsChangedHandler(dataGrid) 

     itemsChangedHandler.Execute(dataGrid.SelectedItems) 

    End Sub 

End Class 

C#:

using Microsoft.VisualBasic; 
using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Data; 
using System.Diagnostics; 
public class SelectedItemsBehavior 
{ 


    public static readonly DependencyProperty SelectedItemsChangedHandlerProperty = DependencyProperty.RegisterAttached("SelectedItemsChangedHandler", typeof(mvvm.RelayCommand), typeof(SelectedItemsBehavior), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnSelectedItemsChangedHandlerChanged))); 



    public static mvvm.RelayCommand GetSelectedItemsChangedHandler(DependencyObject element) 
    { 
     if (element == null) 
      throw new ArgumentNullException("element"); 
     return element.GetValue(SelectedItemsChangedHandlerProperty); 
    } 

    public static void SetSelectedItemsChangedHandler(DependencyObject element, mvvm.RelayCommand value) 
    { 
     if (element == null) 
      throw new ArgumentNullException("element"); 
     element.SetValue(SelectedItemsChangedHandlerProperty, value); 
    } 


    private static void OnSelectedItemsChangedHandlerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     DataGrid dataGrid = (DataGrid)d; 

     if (e.OldValue == null && e.NewValue != null) { 
      dataGrid.SelectionChanged += ItemsControl_SelectionChanged; 
     } 

     if (e.OldValue != null && e.NewValue == null) { 
      dataGrid.SelectionChanged -= ItemsControl_SelectionChanged; 
     } 

    } 



    public static void ItemsControl_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     DataGrid dataGrid = (DataGrid)sender; 

     RelayCommand itemsChangedHandler = GetSelectedItemsChangedHandler(dataGrid); 

     itemsChangedHandler.Execute(dataGrid.SelectedItems); 

    } 

} 

然後我們把它添加到數據網格在XAML:

<DataGrid AutoGenerateColumns="False" FontFamily="Tahoma" FontSize="9" 
      ItemsSource="{Binding Path=ResultsVM}" 
      mvvm:SelectedItemsBehavior.SelectedItemsChangedHandler="{Binding Path=ResultsSelectionChangedCommand}" /> 

然後我們在代碼中RelayCommand ViewModel:

Public ReadOnly Property ResultsSelectionChangedCommand() As mvvm.RelayCommand 
     Get 
      If _resultsSelectionChangedCommand Is Nothing Then 
       _resultsSelectionChangedCommand = New mvvm.RelayCommand(AddressOf ResultsSelectionChanged) 
      End If 
      Return _resultsSelectionChangedCommand 
     End Get 
    End Property 

    Public Sub ResultsSelectionChanged(ByVal selectedItems As Object) 

     _resultsSelectedItems.Clear() 
     For Each item In selectedItems 
      _resultsSelectedItems.Add(item) 
     Next 

    End Sub 

C#:

public mvvm.RelayCommand ResultsSelectionChangedCommand { 
    get { 
     if (_resultsSelectionChangedCommand == null) { 
      _resultsSelectionChangedCommand = new mvvm.RelayCommand(ResultsSelectionChanged); 
     } 
     return _resultsSelectionChangedCommand; 
    } 
} 


public void ResultsSelectionChanged(object selectedItems) 
{ 
    _resultsSelectedItems.Clear(); 
    foreach (item in selectedItems) { 
     _resultsSelectedItems.Add(item); 
    } 

} 

的_resultsSelectedItems簡直是在DataGrid中顯示的項目清單:

Private _resultsSelectedItems As New List(Of WorkOrderMatchViewModel) 

C#:

private List<WorkOrderMatchViewModel> _resultsSelectedItems = new List<WorkOrderMatchViewModel>(); 

希望這有助於有點同時使用的Bill的方法無需參考MVVM-Light。

+0

部分答案會給予好評這一點,如果它不是在VB.NET書面... :) – 2013-08-28 09:11:48

+0

讓我去上工作! – samneric 2013-08-29 16:29:45

+0

我得到的selectedItems不是枚舉....'foreach(item in selectedItems)' – Master 2014-03-19 15:38:34

3

C#版本SelectedItemsBehavior類。可能會幫助某人。

public static class SelectedItemsBehavior 
{ 
    public static readonly DependencyProperty SelectedItemsChangedHandlerProperty = 
     DependencyProperty.RegisterAttached("SelectedItemsChangedHandler", 
      typeof(RelayCommand), 
      typeof(SelectedItemsBehavior), 
      new FrameworkPropertyMetadata(new PropertyChangedCallback(OnSelectedItemsChangedHandlerChanged))); 


    public static RelayCommand GetSelectedItemsChangedHandler(DependencyObject element) 
    { 
     if (element == null) 
     { 
      throw new ArgumentNullException("element"); 
     } 
     return element.GetValue(SelectedItemsChangedHandlerProperty) as RelayCommand; 
    } 

    public static void SetSelectedItemsChangedHandler(DependencyObject element, RelayCommand value) 
    { 
     if (element == null) 
     { 
      throw new ArgumentNullException("element"); 
     } 
     element.SetValue(SelectedItemsChangedHandlerProperty, value); 
    } 

    public static void OnSelectedItemsChangedHandlerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 

     DataGrid dataGrid = (DataGrid)d; 

     if (e.OldValue == null && e.NewValue != null) 
     { 
      dataGrid.SelectionChanged += new SelectionChangedEventHandler(ItemsControl_SelectionChanged); 
     } 

     if (e.OldValue != null && e.NewValue == null) 
     { 
      dataGrid.SelectionChanged -= new SelectionChangedEventHandler(ItemsControl_SelectionChanged); 
     } 
    } 


    public static void ItemsControl_SelectionChanged(Object sender, SelectionChangedEventArgs e) 
    { 

     DataGrid dataGrid = (DataGrid)sender; 

     RelayCommand itemsChangedHandler = GetSelectedItemsChangedHandler(dataGrid); 

     itemsChangedHandler.Execute(dataGrid.SelectedItems); 
    } 
}