c# - 为什么 DataGridRow IsSelected 绑定(bind)不适用于 DataGrid

标签 c# wpf mvvm wpfdatagrid

在 Josh Smith 的 MVVM 演示中,他使用了带有 ListViewItem 样式的 ListView,如下所示:

<Style x:Key="CustomerItemStyle" TargetType="{x:Type ListViewItem}">
    <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="ItemsControl.AlternationIndex" Value="1" />
                <Condition Property="IsSelected" Value="False" />
                <Condition Property="IsMouseOver" Value="False" />
            </MultiTrigger.Conditions>
            <Setter Property="Background" Value="#EEEEEEEE" />
        </MultiTrigger>
    </Style.Triggers>
</Style>

它很好地绑定(bind)了 IsSelected 属性。样式应用于 ListView,如下所示:

<ListView  
  ItemContainerStyle="{StaticResource CustomerItemStyle}"
  ItemsSource="{Binding}"
  >

我的版本

我已尝试通过 DataGridRow 以类似的方式将 IsSelected 与 DataGrid 绑定(bind)。但是,当通过 IsSelected 属性定义的项目 ViewModel 集合选择项目时,它会导致问题。

因为它使用双向绑定(bind),所以我认为可以通过 UI 和项目 ViewModel 的集合来选择项目。

假设我通过 UI 选择项目,这很好用。我可以选择单个项目,然后使用 [shift] 选择一个范围,然后使用 [ctrl] 选择更多项目。取消选择项目也能正常工作。

但是我通过收藏选择了一堆。假设单击一个按钮(就像我在下面的代码中所做的那样),一堆项目被选中。当我向下滚动 DataGrid 然后选择了一些,因为它们应该是一些不是。如果我通过 UI 选择一个项目,那么只有一些项目被取消选择,一些项目保持选中状态,这有点古怪。即使是左上角的“全选”按钮也不太正确。

代码 所有代码都在下面,底部是 View ,关键部分是具有 IsSelected 绑定(bind)的 DataGridRow 样式。

这是我的用户类:

using System.ComponentModel;

namespace WpfAppDataGrid.Model
{
    public class User : INotifyPropertyChanged
    {
        public static User CreateNewUser()
        {
            return new User();
        }

        public User() { }

        public int User_ID { get; set; }
        public string Username { get; set; }
        public string Name { get; set; }
        public string Job_Title { get; set; }
        public string Department { get; set; }
        public string Company { get; set; }
        public string Phone_Office { get; set; }
        public string Phone_Mobile { get; set; }
        public string Email { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

        }
    }
}

这是 IsSelected 所在的 UserViewModel:

using System;
using System.ComponentModel;
using WpfAppDataGrid.DataAccess;
using WpfAppDataGrid.Model;

namespace WpfAppDataGrid.ViewModel
{
    class UserViewModel : INotifyPropertyChanged
    {
        readonly User _user;
        readonly UserRepository _userRepository;
        bool _isSelected;

        public UserViewModel(User user, UserRepository userRepository)
        {
            if (user == null)
                throw new ArgumentNullException("user");

            if (userRepository == null)
                throw new ArgumentNullException("userRepository");

            _user = user;
            _userRepository = userRepository;
        }
        public UserViewModel()
        {
        }

        public int User_ID
        {
            get { return _user.User_ID; }
            set
            {
                if (value == _user.User_ID)
                    return;

                _user.User_ID = value;

                RaisePropertyChanged("User_ID");
            }
        }

        public string Username
        {
            get { return _user.Username; }
            set
            {
                if (value == _user.Username)
                    return;

                _user.Username = value;

                RaisePropertyChanged("Username");
            }
        }
        public string Name
        {
            get { return _user.Name; }
            set
            {
                if (value == _user.Name)
                    return;

                _user.Name = value;

                RaisePropertyChanged("Name");
            }
        }
        public string Job_Title
        {
            get { return _user.Job_Title; }
            set
            {
                if (value == _user.Job_Title)
                    return;

                _user.Job_Title = value;

                RaisePropertyChanged("Job_Title");
            }
        }
        public string Department
        {
            get { return _user.Department; }
            set
            {
                if (value == _user.Department)
                    return;

                _user.Department = value;

                RaisePropertyChanged("Department");
            }
        }
        public string Company
        {
            get { return _user.Company; }
            set
            {
                if (value == _user.Company)
                    return;

                _user.Company = value;

                RaisePropertyChanged("Company");
            }
        }
        public string Phone_Office
        {
            get { return _user.Phone_Office; }
            set
            {
                if (value == _user.Phone_Office)
                    return;

                _user.Phone_Office = value;

                RaisePropertyChanged("Phone_Office");
            }
        }
        public string Phone_Mobile
        {
            get { return _user.Phone_Mobile; }
            set
            {
                if (value == _user.Phone_Mobile)
                    return;

                _user.Phone_Mobile = value;

                RaisePropertyChanged("Phone_Mobile");
            }
        }
        public string Email
        {
            get { return _user.Email; }
            set
            {
                if (value == _user.Email)
                    return;

                _user.Email = value;

                RaisePropertyChanged("Email");
            }
        }

        /// <summary>
        /// Gets/sets whether this customer is selected in the UI.
        /// </summary>
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value == _isSelected)
                    return;

                _isSelected = value;

                RaisePropertyChanged("IsSelected");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

        }
    }
}

这是我的 AllUsersViewModel:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Input;
using WpfAppDataGrid.DataAccess;

namespace WpfAppDataGrid.ViewModel
{
    class AllUsersViewModel : INotifyPropertyChanged
    {
        readonly UserRepository _userRepository;

        public AllUsersViewModel()
        {
            _userRepository = new UserRepository();
            _userRepository.LoadUsers();
            CreateAllUsers();
        }

        void CreateAllUsers()
        {
            List<UserViewModel> all =
                (from usr in _userRepository.GetUsers()
                 select new UserViewModel(usr, _userRepository)).ToList();

            foreach (UserViewModel uvm in all)
            {
                uvm.PropertyChanged += this.OnUserViewModelPropertyChanged;
            }
            this.UserCollection = new ObservableCollection<UserViewModel>(all);
            this.UserCollection.CollectionChanged += this.OnCollectionChanged;
        }

        private ObservableCollection<UserViewModel> userCollection;
        public ObservableCollection<UserViewModel> UserCollection
        {
            get
            {
                return userCollection;
            }
            set
            {
                userCollection = value;
                RaisePropertyChanged("UserCollection");
            }
        }

        RelayCommand selectItemsCommand;

        public ICommand SelectItemsCommand
        {
            get
            {
                if (selectItemsCommand == null)
                    selectItemsCommand = new RelayCommand(SelectItemsCommandExecute, CanSelectItemsCommand);
                return selectItemsCommand;
            }
        }

        private void SelectItemsCommandExecute(object parameter)
        {
            for (int i = 4; i <= 49; i++)
            {
                UserCollection[i].IsSelected = true;
            }
        }

        private bool CanSelectItemsCommand(object parameter)
        {
            return true;
        }

        void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (UserViewModel userVM in e.NewItems)
                    userVM.PropertyChanged += this.OnUserViewModelPropertyChanged;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (UserViewModel userVM in e.OldItems)
                    userVM.PropertyChanged -= this.OnUserViewModelPropertyChanged;

        }

        void OnUserViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            string IsSelected = "IsSelected";

            if (e.PropertyName == IsSelected)
                this.RaisePropertyChanged("TotalSelectedUsers");
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public class RelayCommand : ICommand
    {
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;

        /// <summary>
        /// Creates a new command that can always execute.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
        }

        /// <summary>
        /// Creates a new command.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        /// <param name="canExecute">The execution status logic.</param>
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }

        [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }
}

这是我创建用户的用户存储库:

using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfAppDataGrid.Model;

namespace WpfAppDataGrid.DataAccess
{
    public class UserRepository
    {
        ObservableCollection<User> _users = new ObservableCollection<User>();

        public UserRepository()
        {
        }

        public ObservableCollection<User> GetUsers()
        {
            return _users;
        }

        public void LoadUsers()
        {
            int i = 0;
            while (i < 1000)
            {
                i++;
                var user = new User();
                user.User_ID = i;
                user.Username = RandomString(8, true);
                user.Name = user.Username + " " + RandomString(8, true);
                user.Job_Title = RandomString(8, true);
                user.Department = RandomString(8, true);
                user.Company = RandomString(10, true);
                user.Phone_Office = "07 " + RandomNumber(5200, 6700) + " " + RandomNumber(1000, 9999);
                user.Phone_Mobile = "04 " + RandomNumber(2800, 4500) + " " + RandomNumber(1000, 9999);
                user.Email = user.Username + "@gmail.com";
                _users.Add(user);
            }
        }

        private static Random randomSeed = new Random();
        public static string RandomString(int size, bool lowerCase)
        {
            StringBuilder RandStr = new StringBuilder(size);
            int Start = (lowerCase) ? 97 : 65;

            for (int i = 0; i < size; i++)
                RandStr.Append((char)(26 * randomSeed.NextDouble() + Start));

            return RandStr.ToString();
        }

        private int RandomNumber(int min, int max)
        {
            return randomSeed.Next(min, max);
        }
    }
}

最后是所有用户的 View :

<Window x:Class="WpfAppDataGrid.View.AllUsersView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewmodel="clr-namespace:WpfAppDataGrid.ViewModel"
        Title="AllUsersView" Height="450" Width="820">

    <Window.DataContext>
        <viewmodel:AllUsersViewModel />
    </Window.DataContext>

    <Window.Resources>
        <Style x:Key="UserRowStyle" TargetType="{x:Type DataGridRow}">
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
            <Setter Property="BorderBrush" Value="DarkGray" />
            <Setter Property="BorderThickness" Value="0,0,1,0"/>
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Foreground" Value="Black"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridRow}">
                        <Grid>
                            <Border x:Name="DGR_BackingBorder" BorderBrush="Orange" BorderThickness="1,2,1,2" Background="Transparent">
                            </Border>
                            <Border x:Name="DGR_Border" 
                                    BorderBrush="{TemplateBinding BorderBrush}" 
                                    BorderThickness="1,2,1,2" 
                                    Background="{TemplateBinding Background}"
                                    SnapsToDevicePixels="True">

                                <SelectiveScrollingGrid>
                                    <SelectiveScrollingGrid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                        <ColumnDefinition Width="*" />
                                    </SelectiveScrollingGrid.ColumnDefinitions>
                                    <SelectiveScrollingGrid.RowDefinitions>
                                        <RowDefinition Height="*" />
                                        <RowDefinition Height="Auto" />
                                    </SelectiveScrollingGrid.RowDefinitions>
                                    <DataGridCellsPresenter x:Name="DGR_CellsPresenter" Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                    <DataGridDetailsPresenter x:Name="DGR_DetailsPresenter" Grid.Column="1" Grid.Row="1"
                                                          SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                                          Visibility="{TemplateBinding DetailsVisibility}" />
                                    <DataGridRowHeader Foreground="White" Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                                   Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                                </SelectiveScrollingGrid>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="DGR_Border" Property="BorderBrush" Value="Transparent" />
                                <Setter TargetName="DGR_Border" Property="BorderThickness" Value="1,2,1,2" />
                            </Trigger>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter TargetName="DGR_Border" Property="BorderBrush" Value="DarkOrange"/>
                                <Setter TargetName="DGR_Border" Property="Background" Value="Orange"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="{x:Type DataGridCell}" >
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="Foreground" Value="Black" />
        </Style>
    </Window.Resources>

    <Grid Name="gridUsers" Background="Transparent">

        <DockPanel Background="Transparent" Margin="2,10,2,2" >
            <Grid DockPanel.Dock="Bottom" Margin="0,2,4,2">
                <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" VerticalAlignment="Center">
                    <Button Content="Select rows 5 to 50" Command="{Binding SelectItemsCommand}"/>
                    <TextBlock Text=" Total: " />
                    <ContentPresenter Content="{Binding  ElementName=GenericDataGrid, Path=ItemsSource.Count}" ContentStringFormat="0" />
                </StackPanel>
            </Grid>
            <DataGrid Name="GenericDataGrid" Background="Transparent"  
                      RowStyle="{StaticResource UserRowStyle}"
                      BorderThickness="0" 
                      CanUserReorderColumns="True" 
                      AutoGenerateColumns="False" 
                      ItemsSource="{Binding UserCollection}" 
                      HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
                      CanUserAddRows="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="ID" CanUserReorder="True" IsReadOnly="True" Binding="{Binding Path=User_ID,NotifyOnTargetUpdated=True}" />
                    <DataGridTextColumn Header="Name" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Name}"/>
                    <DataGridTextColumn Header="Username" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Username}"/>
                    <DataGridTextColumn Header="Job Title" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Job_Title}"/>
                    <DataGridTextColumn Header="Department" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Department}"/>
                    <DataGridTextColumn Header="Company" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Company}"/>
                    <DataGridTextColumn Header="Phone" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Phone_Office}"/>
                    <DataGridTextColumn Header="Mobile" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Phone_Mobile}"/>
                    <DataGridTextColumn Header="eMail" CanUserReorder="True" CanUserSort="True" Binding="{Binding Path=Email}"/>
                </DataGrid.Columns>
            </DataGrid>
        </DockPanel>
    </Grid>
</Window>

最佳答案

不要禁用虚拟化!
如果这是一个错误,Microsoft 早就修复了它,因为数据表通常是最常见的数据 View 之一。
WPF 框架不是针对业余爱好者和业余程序员的玩笑。它旨在供专业开发人员用来定制商业丰富的桌面应用程序。如此严重的错误,在那段时间未修复(即未得到服务),将立即取消 WPF 作为一项严肃和专业技术的资格。

一切正常。

您必须设置 Binding.UpdateSourceTrigger Binding 的属性(property)在 DataGridRow.IsSelected 上属性明确为 UpdateSourcetrigger.PropertyChanged .

DataGridRow有多种视觉选择状态,包括未聚焦的选择。 Unfocused selected 是在没有焦点的情况下选择行时的状态,例如通过数据模型选择时。

默认情况下,DataGridRow实际上已被选中,但样式没有为未聚焦状态定义(令人满意的)视觉反馈。

这个“问题”是通过使用简单触发器自定义视觉状态而人为引入的。这是另一个很好的例子,为什么要使用 VisualStateManager总是优于简单的属性 Trigger (当可视化 Control 的视觉状态时)。
后来的框架(如 UWP)强制使用 VisualStateManager (和 VisualState )。
关键是,一个控件可以有多个状态,这些状态通常不会通过属性来表达。状态是相互排斥的,这在通过属性表达这种约束时需要一些额外的努力。 VisualState是表达视觉状态的便捷方式。

以下完整示例 Style目标 DataGridRow展示如何绑定(bind) DataGridRow.IsSelected属性(property)给IsEnabled行项目(数据模型)的属性以及如何更改视觉 Unfocused_Selected状态。

虽然不完整,但它正在充分发挥作用,以证明 DataGrid正在按预期工作 - 启用了 UI 虚拟化。只需调整 DataGrid.ItemsSource绑定(bind)并确保您的数据模型具有 IsEnabled引发 INotifyPropertyChanged.PropertyChanged 的属性(property)事件:

<DataGrid EnableRowVirtualization="True"
          ItemsSource="{Binding DataItems}"
          Height="200">
  <DataGrid.RowStyle>
    <Style TargetType="DataGridRow">
      <Setter Property="IsSelected"
              Value="{Binding IsEnabled, UpdateSourceTrigger=PropertyChanged}" />
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type DataGridRow}">
            <Border x:Name="DGR_Border"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    SnapsToDevicePixels="True"
                    Background="{TemplateBinding Background}">
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal" />

                  <VisualState x:Name="Normal_Selected">
                    <Storyboard>
                      <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                    Storyboard.TargetProperty="(Panel.Background).
              (SolidColorBrush.Color)">
                        <EasingColorKeyFrame KeyTime="0"
                                              Value="DarkRed" />
                      </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>

                  <!-- Unfocused related states -->
                  <VisualState x:Name="Unfocused_Selected">
                    <Storyboard>
                      <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                    Storyboard.TargetProperty="(Panel.Background).
              (SolidColorBrush.Color)">
                        <EasingColorKeyFrame KeyTime="0"
                                              Value="Orange" />
                      </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>

                  <VisualState x:Name="MouseOver_Unfocused_Selected">
                    <Storyboard>
                      <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                    Storyboard.TargetProperty="(Panel.Background).
              (SolidColorBrush.Color)">
                        <EasingColorKeyFrame KeyTime="0"
                                              Value="GreenYellow" />
                      </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>

                  <VisualState x:Name="MouseOver_Unfocused_Editing">
                    <Storyboard>
                      <!-- TODO::Define ColorAnimation -->
                    </Storyboard>
                  </VisualState>

                  <VisualState x:Name="Unfocused_Editing">
                    <Storyboard>
                      <!-- TODO::Define ColorAnimation -->
                    </Storyboard>
                  </VisualState>

                  <!-- Focused states -->
                  <VisualState x:Name="MouseOver">
                    <Storyboard>
                      <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
                                                    Storyboard.TargetProperty="(Panel.Background).
              (SolidColorBrush.Color)">
                        <EasingColorKeyFrame KeyTime="0"
                                              Value="CornflowerBlue" />
                      </ColorAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>

                  <VisualState x:Name="MouseOver_Selected">
                    <Storyboard>
                      <!-- TODO::Define ColorAnimation -->
                    </Storyboard>
                  </VisualState>

                  <VisualState x:Name="Normal_Editing">
                    <Storyboard>
                      <!-- TODO::Define ColorAnimation -->
                    </Storyboard>
                  </VisualState>

                  <VisualState x:Name="MouseOver_Editing">
                    <Storyboard>
                      <!-- TODO::Define ColorAnimation -->
                    </Storyboard>
                  </VisualState>

                  <VisualState x:Name="Normal_AlternatingRow">
                    <Storyboard>
                      <!-- TODO::Define ColorAnimation -->
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>

              <SelectiveScrollingGrid>
                <SelectiveScrollingGrid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto" />
                  <ColumnDefinition Width="*" />
                </SelectiveScrollingGrid.ColumnDefinitions>
                <SelectiveScrollingGrid.RowDefinitions>
                  <RowDefinition Height="*" />
                  <RowDefinition Height="Auto" />
                </SelectiveScrollingGrid.RowDefinitions>
                <DataGridCellsPresenter Grid.Column="1"
                                        ItemsPanel="{TemplateBinding ItemsPanel}"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                <DataGridDetailsPresenter Grid.Column="1"
                                          Grid.Row="1"
                                          Visibility="{TemplateBinding DetailsVisibility}"
                                          SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, 
        ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical},
        Converter={x:Static DataGrid.RowDetailsScrollingConverter}, 
        RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                <DataGridRowHeader Grid.RowSpan="2"
                                    SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                    Visibility="{Binding HeadersVisibility, 
        ConverterParameter={x:Static DataGridHeadersVisibility.Row}, 
        Converter={x:Static DataGrid.HeadersVisibilityConverter}, 
        RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
              </SelectiveScrollingGrid>
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </DataGrid.RowStyle>
</DataGrid>

关于c# - 为什么 DataGridRow IsSelected 绑定(bind)不适用于 DataGrid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23441113/

相关文章:

c# - 从链接到 SQL 数据库的数据集中有效删除行

c# - 在哪里可以找到 GetMemberInfo

c# - 获取委托(delegate)的 IntPtr 并调用

wpf - 如何绑定(bind)到 IronPython 中的 ListBox?

c# - 无法定义两个对象之间的关系

c# - NFC Action_Tech_Discovered with foreground dispatch 不会捕获 Mifare 1k 卡

wpf - 我可以在 CompositionTarget.Rendering 中做什么?

c# - 如何在堆栈面板中滚动数据网格?

javascript - 当未观察到底层数据时,Knockout.js 计算写入不会触发突变事件

c# - 如何从大型ViewModel中分离出命令