9

私は WPF Toolkit の DataGrid を使用しています。行の複数選択を可能にするために、DataGrid のプロパティを有効にしました。SelectedItems を取得するにはどうすればよいですか? ViewModel を View にバインドするために MVVM フレームワークを使用しています。

ありがとう!

4

4 に答える 4

7

ビルの答えを取り入れて、オプション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}" />

次に、ViewModelでRelayCommandをコーディングします。

    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>();

これがお役に立てば幸いです。MVVM-Lightを参照しなくても、Billの両方の方法を使用できます。

于 2011-06-07T19:29:34.373 に答える
4

私もこの質問に対する答えを探していました。私が見つけた答えは、

SelectedItems1) 分離コードで、データグリッドからリストを渡す ViewModel のメソッドに作業を委譲します。このコレクションには、選択されたすべてのアイテムが含まれます。

または

2) MVVM ツールキット ライトを使用して、Event to Command を使用し、オブジェクトをパラメータとして ViewModel に直接渡すことができます。

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

この場合SelectionChanged、xamlselectionchanged内の をコード ビハインド内の にバインドする必要があります。次に、コード ビハインドでこのリストを保存し、選択した行の削除などに使用できます。

これを行うためのより良い方法があれば、私は知りたいです。

HTH

明細書

于 2009-11-24T14:01:06.750 に答える
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);
    }
}
于 2011-08-24T12:06:57.167 に答える
2

Bill が述べたように、リレー コマンドを使用してこれを回避することができました。部分的に少し汚れていますが、ビハインド ファイルにコードを入れることは避けました。

まず、XAML で、コマンドをボタンまたは RelayCommand をトリガーするものにバインドします。

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

コマンド パラメーター Binds が別の UI 要素 (選択した項目を取得する DataGrid または ListView) にあることに気付くでしょう。この構文は、要素間のバインディングをサポートするようになったため、WPF だけでなく Silverlight 3 でも機能します。

ビューモデルでは、コマンドは次のようになります

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 パターンをそのまま維持します。

于 2009-12-03T01:59:16.357 に答える