WPF Datagrid:加载时,选择当前项目(突出显示)

时间:2011-03-04 21:53:46

标签: wpf datagrid initialization selection highlighting

我有一个绑定到ViewModel

中某些属性的WPF Datagrid
<DataGrid AutoGenerateColumns="False" Name="dataGrid" SelectionMode="Single"
          ItemsSource="{Binding ItemList}" SelectedItem="{Binding SelectedItem}">
...
</DataGrid>

当我的窗口加载和Datagrid时,我设置了SelectedItem并且它绑定得很好但行没有突出显示。单击一行时,行突出显示并解决问题。

如何在加载/初始化时设置/触发DataGrid中SelectedItem的突出显示?

修改

它实际上被选中了,因为我有一个小选择单元格。它只是不会触发的突出显示的渲染。

enter image description here

5 个答案:

答案 0 :(得分:7)

当使用Model作为WPF窗口的DataContext时,DataGrid的SelectionChanged事件直到加载Window之后才会被调用,这就是为什么行永远不会突出显示而你只能看到第一行部分亮点。可能有更优雅的方式,但这是一个解决方法。

在Window加载的事件或DataGrid的加载事件中,重置SelectedItem绑定:

public MainWindow()
{
    InitializeComponent(); 
    this.Loaded += new RoutedEventHandler( OnLoaded );
}

// could also be placed in the DataGrid's loaded event handler
private void OnLoaded( object sender, RoutedEventArgs e )
{
    if( dataGrid != null && Model.SelectedItem != null )
    {
        var selected = Model.SelectedItem;
        Model.SelectedItem = null;
        Model.SelectedItem = selected;
    }
}

这是一份完整的工作样本。

<强> XAML

<Window x:Class="WpfDataGridHighlightOnLoad.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:model="clr-namespace:WpfDataGridHighlightOnLoad" 
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <model:MainWindowModel x:Name="Model" />
    </Window.DataContext>

    <Grid>
        <DataGrid AutoGenerateColumns="True" SelectionMode="Single"
                  HorizontalAlignment="Stretch" 
                  Name="dataGrid" 
                  VerticalAlignment="Top"
                  ItemsSource="{Binding ItemList}"
                  SelectedItem="{Binding SelectedItem}">
        </DataGrid>

        <Button Content="Cycle Selection" Click="OnCycleClick" 
                Height="23" 
                HorizontalAlignment="Right" 
                Name="button1" 
                VerticalAlignment="Bottom" Width="125" />

        <Button Content="Reset Grid" Click="OnResetClick" 
                Height="23" 
                HorizontalAlignment="Left" 
                Name="button2" 
                VerticalAlignment="Bottom" Width="125" />

    </Grid>
</Window>

代码背后

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace WpfDataGridHighlightOnLoad
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();   
            this.Loaded += new RoutedEventHandler( OnLoaded );
        }

        // could also be placed in the DataGrid's loaded event handler
        private void OnLoaded( object sender, RoutedEventArgs e )
        {
            if( dataGrid != null && Model.SelectedItem != null )
            {
                var selected = Model.SelectedItem;
                Model.SelectedItem = null;
                Model.SelectedItem = selected;
            }
        }

        private void OnCycleClick( object sender, RoutedEventArgs e )
        {
            int index = Model.ItemList.IndexOf( Model.SelectedItem );
            index = index == Model.ItemList.Count - 1 ? 0 : index + 1;
            Model.SelectedItem = Model.ItemList[index];
        }

        private void OnResetClick( object sender, RoutedEventArgs e )
        {
            Model.Reset();
        }
    }

    public class MainWindowModel : INotifyPropertyChanged
    {
        public MainWindowModel()
        {
            Reset();
        }

        public void Reset()
        {
            ItemList = new List<Person>
                           {
                               new Person("Joe", 20),
                               new Person("John", 30),
                               new Person("Jane", 40),
                               new Person("Jill", 50),
                               new Person("Fido", 7),
                           };

            SelectedItem = ItemList[2];
        }

        private Person _selectedItem;
        public Person SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                NotifyPropertyChanged( "SelectedItem" );
            }
        }

        private List<Person> _itemList;
        public List<Person> ItemList
        {
            get { return _itemList; }
            set
            {
                _itemList = value;
                NotifyPropertyChanged( "ItemList" );
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged( String info )
        {
            if( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( info ) );
            }
        }

        #endregion
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public Person( string name, int age )
        {
            Name = name;
            Age = age;
        }

        public override string ToString()
        {
            return Name;
        }
    }
}

答案 1 :(得分:7)

我有同样的“问题”,最后找到了一个很好的解决方案。正如您已经说过的那样,并不是选择了行,而是没有突出显示该行。如果仔细观察,您会注意到当您单击行中的任何位置(使用鼠标)时,它仍然不会突出显示该行,只会突出显示该行中的单元格。

所以2个选项;

  • 创建代码以选择行的单元格
  • 或创建一个Style.Trigger来突出显示该行(这是我脑海中最好的选择)。

为此,请将此类内容添加到xaml-file中的datagrid:

            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="DodgerBlue"/>
                            <Setter Property="Foreground" Value="White"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.RowStyle>

希望它有所帮助!

干杯, LTB

答案 2 :(得分:0)

这有点旧,但任何帖子中的答案似乎都没有完全正确。你想要的是它按照它应该工作的方式工作:即无论控件是否有焦点(这似乎是附带的东西),突出显示都是相同的。

这可以使用DataGridRow样式完成,但诀窍不是自己指定颜色,而是使用默认颜色,所以一切正常。一个额外的烦恼来自这样一个事实:它是突出显示的单元格,而不是行,所以你基本上需要复制单元格高亮样式:

<Style
    x:Key="DataGridRowStyle"
    TargetType="{x:Type DataGridRow}">
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition
                    Property="IsKeyboardFocusWithin"
                    Value="False" />
                <Condition
                    Property="IsSelected"
                    Value="True" />
            </MultiTrigger.Conditions>
            <Setter
                Property="Background"
                Value="{DynamicResource
                    {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}" />
            <Setter
                Property="Foreground"
                Value="{DynamicResource
                    {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}" />
        </MultiTrigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition
                    Property="IsKeyboardFocusWithin"
                    Value="True" />
                <Condition
                    Property="IsSelected"
                    Value="True" />
            </MultiTrigger.Conditions>
            <Setter
                Property="Background"
                Value="{DynamicResource
                    {x:Static SystemColors.HighlightBrushKey}}" />
            <Setter
                Property="Foreground"
                Value="{DynamicResource
                    {x:Static SystemColors.HighlightTextBrushKey}}" />
        </MultiTrigger>
    </Style.Triggers>
</Style>

注意有一个问题,即设置行上下文菜单需要覆盖DataGridRow上的DataGrid样式,所以如果你在全局范围内执行此操作并且它不起作用,请检查您的RowStyle尚未被覆盖。

答案 3 :(得分:0)

遇到同样的问题,在将伪数据插入WPF DataGrid时,然后尝试更改行顺序。排高亮的行(图片如下)。

原因是插入了确切的&#34;相同的&#34;多次记录对象。

enter image description here

//Ex: Messes up highlighting.    
grid.Items.Add(rowObj);
grid.Items.Add(rowObj);
grid.Items.Add(rowObj);

//Ex: Highlighting OK.  Create a new object each time.  Even if all columns have exact same values.  
rowobj = new .....
grid.Items.Add(rowObj);

rowobj = new .....
grid.Items.Add(rowObj);

答案 4 :(得分:0)

我知道这个线程非常老,但是没有一个解决方案对我有帮助。

如果有人遇到同样的问题,我发现一个非常简单的解决方案是在将其选定的项目加载时将焦点简单地设置到数据网格。

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    dataGrid.Focus();
    // Set selected item in datagrid
}