WPF Datagrid: при загрузке, выбор текущего элемента (выделение)

У меня есть WPF Datagrid, привязанный к некоторым свойствам в моей ViewModel

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

когда мое окно загружается и Datagrid тоже, я устанавливаю SelectedItem и он связывается нормально, но строка не подсвечивается. В тот момент, когда я нажимаю строку, выделите строку и проблема будет решена.

как я могу установить/запустить подсветки SelectedItem в DataGrid при загрузке/инициализации ?

EDIT:

он на самом деле выбран, потому что у меня есть маленькая ячейка отбора. Это просто рендеринг подсветки, который не срабатывает.

enter image description here

5 ответов


при использовании модели в качестве DataContext для окна WPF DataGrid SelectionChanged событие не вызывается до тех пор, пока окно не будет загружено, поэтому строка никогда не выделяется, и вы видите только первую строку с частичной подсветкой. Возможно, есть более элегантный способ, но вот обходной путь.

в событии loaded окна или событии loaded 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;
        }
    }
}

У меня была такая же "проблема" и, наконец, нашел довольно хорошее решение проблемы. Как вы уже сказали, не то, что строка не выбрана, но что она не выделяет строку. Если вы внимательно посмотрите, вы заметите, что при нажатии в любом месте строки (с помощью мыши) он по-прежнему не выделяет строку, только ячейки внутри нее.

Итак, 2 варианта;

  • создать код для выбора клетки строки
  • или создать стиль.Триггер выделите строку (которая является лучшим вариантом на мой взгляд).

чтобы сделать это, добавьте что-то вроде этого в datagrid в 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


Это немного старый, но ни один из ответов в любом посте, кажется,не совсем правильно. Вы хотите, чтобы он работал так, как должен был работать: т. е. подсветка одинакова независимо от того, был ли у элемента управления фокус (что кажется чем-то случайным).

Это можно сделать с помощью 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 не был отменен.


столкнулся с той же проблемой при вставке фиктивных данных в DataGrid WPF, а затем пытается изменить порядок строк. Строка hightlighting отключилась (изображение ниже).

причиной была вставка точного" того же " объекта записи несколько раз.

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

Я знаю, что этот поток очень старый, но ни одно из решений не помогло мне.

Если у кого-то есть такая же проблема, очень простым решением, которое я нашел, было просто установить фокус на datagrid перед установкой выбранного элемента При загрузке.

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