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

发布于 2024-10-20 15:53:25 字数 574 浏览 4 评论 0原文

我有一个 WPF Datagrid 绑定到我的 ViewModel 中的某些属性。

<DataGrid AutoGenerateColumns="False" Name="dataGrid" SelectionMode="Single"
          ItemsSource="{Binding ItemList}" SelectedItem="{Binding SelectedItem}">
...
</DataGrid>

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

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

编辑:

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

在此处输入图像描述

I have a WPF Datagrid binded to some properties in my ViewModel

<DataGrid AutoGenerateColumns="False" Name="dataGrid" SelectionMode="Single"
          ItemsSource="{Binding ItemList}" SelectedItem="{Binding SelectedItem}">
...
</DataGrid>

When my window load and the Datagrid too, I set the SelectedItem and it binds fine but the row isn't highlighted. The moment I click a row, the row highlight and the problem is resolved.

How can I set/trigger the highlighting of the SelectedItem in the DataGrid on load/initialization ?

EDIT:

It's actually selected because I have the little selection cell. It's just the rendering of the Highlighting that does not trigger.

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一曲爱恨情仇 2024-10-27 15:53:25

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

所以有2个选择;

  • 创建代码来选择行的单元格
  • 或创建 Style.Trigger 来突出显示该行(这是我认为最好的选择)。

为此,请将类似以下内容添加到 xaml 文件中的数据网格中:

            <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

I had the same "problem" and finally found a pretty good solution to the problem. As you already said is not that the row isn't selected but that it does not highlight the row. If you watch carefully you will notice that when you click anywhere in the row (using the mouse) it still doesn't highlight the row, only the cells inside it.

So 2 options;

  • Create code to select the cells of the row
  • or create a Style.Trigger to highlight the row (which is the best option in my mind).

To do this, add something like this to the datagrid in the xaml-file:

            <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>

Hope it helps!

Cheers,
LTB

美男兮 2024-10-27 15:53:25

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

在 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;
        }
    }
}

When using a Model as the DataContext for a WPF Window, the DataGrid's SelectionChanged event doesn't get called until after the Window is loaded which is why the row is never highlighted and you only see the first row with the partial highlight. There may be a more elegant way, but here's a work-around.

In the Window's loaded event or the DataGrid's loaded event, reset the SelectedItem binding:

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;
    }
}

Here's a complete working sample.

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>

Code Behind

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;
        }
    }
}
ゞ记忆︶ㄣ 2024-10-27 15:53:25

这有点老了,但任何帖子中的答案似乎都不太正确。您想要的是它按照预期的方式工作:即,无论控件是否具有焦点,突出显示都是相同的(这似乎是偶然的)。

这可以使用 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>

请注意,有一个陷阱,要设置行上下文菜单,您需要覆盖 < code>DataGridRow 样式在 DataGrid 上,因此,如果您全局执行此操作并且它不起作用,请检查您的 RowStyle 是否未被覆盖。

This is a bit of an old one, but none of the answers in any post seem to get it quite right. What you want is it to work the way it was supposed to work: i.e. the highlighting is the same whether or not the control ever had focus (which seems like something that is incidental).

This can be done with a DataGridRow style, but the trick is not to specify the colors yourself, but to use the default colors, so everything just works. An extra annoyance comes from the fact that it is the cells that get highlighted, not the rows, so you basically need to duplicate the cell highlighting style:

<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>

Note there is a gotcha, that to set the row context menu you need to override the DataGridRow style on the DataGrid, so if you do this globally and it isn't working, check that your RowStyle hasn't been overridden.

始终不够爱げ你 2024-10-27 15:53:25

将虚拟数据插入 WPF DataGrid,然后尝试更改行顺序时,遇到了同样的问题。行突出显示隐藏起来(下图)。

原因是多次插入完全相同的“相同”记录对象。

输入图片此处描述

//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);

Ran across same issue, when inserting dummy data into a WPF DataGrid, then trying to alter row order. The row hightlighting bunked out (image below).

Cause was inserting the exact "same" record object multiple times.

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);
夜访吸血鬼 2024-10-27 15:53:25

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

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

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

I know this thread is super old, but none of the solutions helped me.

If someone is having the same sort of issue, a very simple solution I've found was to simply set focus to the datagrid before setting its selected item on load.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    dataGrid.Focus();
    // Set selected item in datagrid
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文