如何以排序安全的方式绑定到DataGridRow的IsSelected属性?

时间:2014-01-30 16:39:01

标签: c# wpf xaml sorting datagrid

作为我正在处理的项目的一部分,我需要绑定到DataGridRow的IsSelected属性。我们在ViewModel中使用此绑定来确定如何显示数据(根据选择的项目数量而变化)。另外,我们使用IsSelected值在Grid上手动选择值,而不必让我们的ViewModel了解DataGrid本身。

在大多数情况下,我们的工作正常(参见简化示例)。问题是当我们开始使用默认的DataGrid排序时。在这一点上,双向绑定使我们得到一些意想不到的结果。要查看此行为:

  1. 运行提供的示例代码
  2. 点击“John”,这将导致该行上的“已选中”复选框被选中
  3. 点击“名称”标题进行排序。
  4. 点击“David”将选择更改为David的行。
  5. 点击“名称”标题再次排序。
  6. 此时你可以看到我们现在莫名其妙地选择并检查了2行(John和David)。
  7. 正如你所看到的那样,只要你不进行排序,绑定就可以正常工作,然后它就会变得混乱。我需要一种方法来绑定IsSelected属性,而不会在排序后出现意外行为。请注意:我理解通过将绑定模式更改为OneWayToSource可以获得我需要的大部分内容,但我确实需要双向绑定。

    提前感谢您的帮助!

    XAML:

    <Window x:Class="DataGridTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <DataGrid Name="UIDataGrid" AutoGenerateColumns="False" IsReadOnly="True">
                <DataGrid.Resources>
                    <Style TargetType="{x:Type DataGridRow}">
                        <Setter Property="IsSelected" Value="{Binding IsSelected}"></Setter>
                    </Style>
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridCheckBoxColumn Header="Selected" Binding="{Binding Path=IsSelected}"></DataGridCheckBoxColumn>
                    <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>
    

    代码背后:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    
    namespace DataGridTest
    {
        public partial class MainWindow : Window
        {
    
            public ObservableCollection<Selectable> Selectables { get; set; }
    
            public MainWindow()
            {
                InitializeComponent();
    
                Selectables = new ObservableCollection<Selectable>();
                Selectables.Add(new Selectable {Name = "Adam", IsSelected = false});
                Selectables.Add(new Selectable {Name = "John", IsSelected = false});
                Selectables.Add(new Selectable {Name = "David", IsSelected = false});
    
                UIDataGrid.ItemsSource = Selectables;
            }
        }
    
        public class Selectable : PropertyChangedNotifier
        {
            private bool _isSelected;
            public bool IsSelected
            {
                get{ return _isSelected; }
                set
                {
                    _isSelected = value;
                    RaisePropertyChanged("IsSelected");
                }
            }
    
            private string _name;
            public string Name
            {
                get { return _name; }
                set
                {
                    _name = value;
                    RaisePropertyChanged("Name");
                }
            }
        }
    
        [Serializable]
        public abstract class PropertyChangedNotifier : INotifyPropertyChanged
        {
            [field: NonSerialized]
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected void RaisePropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
    

1 个答案:

答案 0 :(得分:1)

您需要在DataTable上将选择模式设置为单一。当我使用您的示例代码执行此操作时,它按照您的预期方式工作。

 <DataGrid Name="UIDataGrid" AutoGenerateColumns="False" SelectionMode="Single" IsReadOnly="True">