14

複数選択が有効になっているデータグリッドがあります。ビューモデルの選択を変更する必要があります。ただし、SelectedItems プロパティは読み取り専用であり、viewmodel のプロパティに直接バインドすることはできません。では、選択が変更されたことをビューに通知するにはどうすればよいでしょうか。

4

4 に答える 4

18

アンディは正しいです。DataGridRow.IsSelectedは、ViewModel からの選択を制御するためにデータバインドできる依存関係プロパティです。次のサンプル コードは、これを示しています。

<Window x:Class="DataGridMultiSelectSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:tk="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <tk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" EnableRowVirtualization="False">
            <tk:DataGrid.Columns>
                <tk:DataGridTextColumn Header="Value" Binding="{Binding Value}" />
            </tk:DataGrid.Columns>
            <tk:DataGrid.RowStyle>
                <Style TargetType="tk:DataGridRow">
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                </Style>
            </tk:DataGrid.RowStyle>
        </tk:DataGrid>
        <Button Content="Select Even" Click="Even_Click" />
        <Button Content="Select Odd" Click="Odd_Click" />
    </StackPanel>
</Window>

using System.ComponentModel;
using System.Windows;

namespace DataGridMultiSelectSample
{
    public partial class Window1
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = new[]
                              {
                                  new MyViewModel {Value = "Able"},
                                  new MyViewModel {Value = "Baker"},
                                  new MyViewModel {Value = "Charlie"},
                                  new MyViewModel {Value = "Dog"},
                                  new MyViewModel {Value = "Fox"},
                              };
        }

        private void Even_Click(object sender, RoutedEventArgs e)
        {
            var array = (MyViewModel[]) DataContext;
            for (int i = 0; i < array.Length; ++i)
                array[i].IsSelected = i%2 == 0;
        }

        private void Odd_Click(object sender, RoutedEventArgs e)
        {
            var array = (MyViewModel[])DataContext;
            for (int i = 0; i < array.Length; ++i)
                array[i].IsSelected = i % 2 == 1;
        }
    }

    public class MyViewModel : INotifyPropertyChanged
    {
        public string Value { get; set; }

        private bool mIsSelected;
        public bool IsSelected
        {
            get { return mIsSelected; }
            set
            {
                if (mIsSelected == value) return;
                mIsSelected = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

必ずEnableRowVirtualisation="False"DataGrid 要素に設定してください。そうしないと、IsSelected バインディングが適切に機能しなくなるリスクがあります。

于 2010-04-10T23:51:19.880 に答える
6

私はあまり を扱ったことはありませんが、 にDataGrid有効なテクニックの 1 つは、個人のプロパティListViewにバインドすることです。リスト内の各オブジェクトに対してこれを設定するだけで、選択されます。IsSelectedListViewItemtrue

の行を表すオブジェクトにDataGridIsSelectedプロパティがあり、この方法でも使用できるのではないでしょうか?

于 2010-04-10T22:43:36.493 に答える
3

みんな、助けてくれてありがとう。私の問題は解決しました。この問題は新しいWPF開発者にはかなり一般的だと思うので、他の誰かが同じ種類の問題に遭遇した場合に備えて、問題と解決策をここで詳しく説明します。

問題:オーディオファイルの複数選択が有効なデータグリッドがあります。グリッドには複数の列ヘッダーがあります。ユーザーは複数の行を複数選択できます。彼が[再生]ボタンをクリックすると、オーディオファイルは列ヘッダー(列Aなど)の順に再生されます。再生が開始されると、複数選択がクリアされ、現在再生中のファイルのみが強調表示されます。すべてのファイルの再生が終了すると、複数選択が再表示されます。再生はビューモデルで行われます。ご覧のとおり、ここには2つの問題があります。1)ビューモデルから現在再生中のファイルを選択する方法と、2)再生が終了したことをビューモデルからビューに通知し、複数選択を再表示する方法です。

解決策:最初の問題を解決するために、ビューのSelectedIndexプロパティにバインドされているプロパティをビューモデルに作成して、現在再生中のファイルを選択しました。2番目の問題を解決するために、ビューモデルにブールプロパティを作成して、再生が終了したことを示しました。ビューのコードビハインドで、ブールプロパティのPropertyChangedイベントをサブスクライブしました。イベントハンドラーでは、ビューのSelectedItemsプロパティが、保存された複数選択から再作成されます(SelectedItemsの内容がリストに保存され、再生開始時にSelectedItemsがクリアされました)。最初は、SelectedItemsを再作成するのに苦労しました。問題は、再作成が2番目のスレッドを介して開始されたという事実が原因であることが判明しました。WPFはそれを許可していません。これに対する解決策は、ディスパッチャを使用することです。()を呼び出して、メインスレッドに作業を任せます。これは、経験豊富な開発者にとっては非常に単純な問題かもしれませんが、初心者にとっては小さな課題です。とにかく、さまざまな人々からの多くの助け。

于 2010-04-14T04:05:10.970 に答える
2

MultiSelector 派生クラスで SelectedItems を使用し、それが返す IList でメソッド Add、Remove、Clear を使用するだけです。

于 2011-07-19T08:38:03.483 に答える