6

MVVMを使用してWPF 4.0でDataGridを作成しようとしています...

必要な機能 -

  1. Muti - チェックボックスを使用して行を選択 (シングルクリック)
  2. データグリッドのすべてのチェックボックスをチェックするすべてのチェックボックスを選択

このようなもの -

ここに画像の説明を入力

2日経ちましたが、問題を効果的に解決する方法がわかりません..

実用的な例は、私が今すぐ必要としているものです..

誰かが私と共有できる実用的な解決策を持っているなら、私は非常に感謝しています...

何もうまくいかなかったので、このことをグーグルで検索するように言わないでください...

アップデート -

  1. 列の自動生成を使用しています
  2. モデルに「IsSelected」またはそのようなプロパティを追加したくありません..
  3. 私はちょうど2つの問題に直面しています -

まず、「すべて選択」機能、つまり、列ヘッダーにあるチェックボックスのクリックですべてのチェックボックスをチェックします...(データグリッドを選択および選択解除できますが、チェックボックスをオン/オフにすることはできません)

第二に、Ctrlキーを押さずにマウスクリックで複数選択..

4

3 に答える 3

20

MVVM を使用する場合、データと見なされるものと、厳密には UI と見なされるものに注意する必要があります。

SelectedItemsデータの一部になるのか、それとも UI だけになるのか?

それがデータの一部である場合はIsSelected、データ クラスを拡張してプロパティを含めるか、 と のみを含むラッパー クラスを作成することを意味する場合でも、データ モデルにプロパティがIsSelected必要です。を保持できるため、最初のオプションがおそらく好まれます。これにより、列のバインドがより簡単になります。bool IsSelectedobject MyDataItemAutoGenerateColumns="True"

次に、データ項目DataGridRow.SelectedItemのプロパティにバインドします。IsSelected

<Style TargetType="{x:Type DataGridRow}">
    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>

ただしSelectedItems、UI のみの場合、またはこのインスタンスで何らかの理由で MVVM パターンを壊している場合は、バインドされていないものを作成し、CheckBoxコード ビハインドを使用して、CheckBoxが に正しく同期されるようにすることができますSelectedItem

簡単なサンプル アプリを作成しました。コードは次のようになります。

まず、. を使用してバインドされていないCheckBox列を列リストに追加しましたDataGridTemplateColumn。これはAutoGenerateColumns、列のリストの前に追加されます。

<DataGrid x:Name="TestDataGrid" ItemsSource="{Binding Test}" 
          SelectionMode="Extended" CanUserAddRows="False"
          PreviewMouseLeftButtonDown="TestDataGrid_PreviewMouseLeftButtonDown_1">
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox x:Name="TestCheckBox"
                              PreviewMouseLeftButtonDown="CheckBox_PreviewMouseLeftButtonDown" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

次に、行のプロパティを設定するPreviewMouseDownイベントをに追加しました。CheckBoxIsSelected

private void CheckBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var chk = (CheckBox)sender;
    var row = VisualTreeHelpers.FindAncestor<DataGridRow>(chk);
    var newValue = !chk.IsChecked.GetValueOrDefault();

    row.IsSelected = newValue;
    chk.IsChecked = newValue;

    // Mark event as handled so that the default 
    // DataGridPreviewMouseDown doesn't handle the event
    e.Handled = true;
}

をナビゲートして、クリックしたものに関連付けられているVisualTreeを見つけて選択する必要があります。生活を楽にするために、ブログで を見つけるためにいくつかのカスタム VisualTreeHelper を使用しています。同じコードを使用することも、独自のメソッドを作成して を検索することもできます。DataGridRowCheckBoxDataGridRowVisualTree

そして最後に、ユーザーが 以外の場所をクリックした場合、デフォルトの選択イベントCheckBoxを無効にします。DataGridこれにより、IsSelectedをクリックしたときにのみ値が変更されるようになりますCheckBox

さまざまなレベルで選択を無効にする方法は複数ありますが、簡単にするためにDataGrid.PreviewMouseLeftButtonDown、ユーザーが をクリックしなかった場合はイベントを無効にしましたCheckBox

private void TestDataGrid_PreviewMouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
{
    var chk = VisualTreeHelpers.FindAncestor<CheckBox>((DependencyObject)e.OriginalSource, "TestCheckBox");

    if (chk == null)
        e.Handled = true;
}

カスタムVisualTreeHelpersを再度使用してビジュアル ツリーをナビゲートし、CheckBox がクリックされたかどうかを確認し、ユーザーが 以外の場所をクリックした場合はイベントをキャンセルしますCheckBox

または項目を追加CheckBoxする2 番目の要求については、これもまた、選択が UI の一部であるかデータの一部であるかによって異なります。SelectAllUnselectAll

UI の一部である場合は、 に を追加するだけで、CheckBoxクリックされDataGridTemplateColumn.HeaderTemplateたときに をループし、最初の列でDataGrid.Rowsを見つけて、CheckBoxオンまたはオフにします。

それがデータの一部である場合でも、同じことを行うことができます ( のDataGrid.Items代わりに にバインドされた値を設定するだけCheckBox.IsCheckedですDataGrid.Rows) 。ViewModel

于 2013-06-16T15:36:30.947 に答える