WPF DataGrid多选绑定

时间:2010-04-10 22:36:39

标签: wpf datagrid multi-select

我有一个启用了多选的数据网格。我需要在viewmodel中更改选择。但是,SelectedItems属性是只读的,不能直接绑定到viewmodel中的属性。那么我如何向视图发出选择已经改变的信号?

4 个答案:

答案 0 :(得分:17)

安迪是对的。 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;
    }
}

确保在DataGrid元素上设置EnableRowVirtualisation="False",否则可能会导致IsSelected绑定失效。

答案 1 :(得分:6)

我没有使用DataGrid,但是一种适用于ListView的技术是绑定到个人IsSelected的{​​{1}}属性。只需将列表中的每个对象设置为ListViewItem,然后它就会被选中。

也许代表true中某行的对象也有DataGrid属性,也可以这样使用?

答案 2 :(得分:3)

伙计们,感谢您的帮助。我的问题解决了。我认为这个问题对于新的WPF开发人员来说非常普遍,所以我会在这里重述我的问题和解决方案,以防其他人遇到同样的问题。

问题:我有一个多选启用的音频文件数据网格。网格有多个列标题。用户可以多选几行。当他点击“播放”按钮时,音频文件将按列标题中的一个顺序播放(比如列A)。播放开始时,将清除多重选择并仅突出显示当前播放的文件。当所有文件的播放完成后,将重新显示多项选择。播放在viewmodel中完成。正如您所看到的,这里存在两个问题:1)如何从viewmodel中选择当前播放的文件,以及2)如何从viewmodel向视图发信号通知播放完成并重新显示多选。 / p>

解决方案:为了解决第一个问题,我在viewmodel中创建了一个属性,该属性绑定到视图的SelectedIndex属性以选择当前播放的文件。为了解决第二个问题,我在视图模型中创建了一个布尔属性来指示播放已完成。在后面的视图代码中,我订阅了boolean属性的PropertyChanged事件。在事件处理程序中,从保存的多选中重新创建视图的SelectedItems属性(SelectedItems的内容已保存到列表中,并且在播放开始时已清除SelectedItems)。起初,我无法重新创建SelectedItems。事实证明,问题是由于重新创建是通过第二个线程启动的。 WPF不允许这样做。解决方法是使用Dispatcher.Invoke()让主线程完成工作。对于有经验的开发人员来说,这可能是一个非常简单的问题,但对于新手来说,这是一个小小的挑战。无论如何,来自不同的人的很多帮助。

答案 3 :(得分:2)

只需在任何MultiSelector派生类上使用SelectedItems,并在它返回的IList上使用Add,Remove,Clear方法。

问候, 罗宾