简体   繁体   中英

How do I highlight a row in the WPF DataGrid when SelectionMode is set to Cell

I have a DataGrid bound to a DataTable in a WPF application. The SelectionUnit of the DataGrid has to be set to Cell, but I'd also like to add a subtle highlight to the whole row so that on wide DataGrids, when the user scrolls off the selected cell they can still see the row highlighted.

This is a little problematic since the IsSelected property of the DataGridRow never gets set to true, because the Row isn't selected, the Cell is.

I don't mind is it's a little arrow in a sticky RowSelector or a highlight applied to the whole Row. Just need some way of highlighting which row is selected.

I've played a bit here, nothing spectacular but is a working version:

    <Style TargetType="DataGridCell">
       <EventSetter Event="Selected" Handler="EventSetter_OnHandlerSelected"/>
       <EventSetter Event="LostFocus" Handler="EventSetter_OnHandlerLostFocus"/>
    </Style>

This is the codebehind:

    private void EventSetter_OnHandlerSelected(object sender, RoutedEventArgs e)
    {
        DataGridRow dgr = FindParent<DataGridRow>(sender as DataGridCell);
        dgr.Background = new SolidColorBrush(Colors.Red);
    }

    private void EventSetter_OnHandlerLostFocus(object sender, RoutedEventArgs e)
    {
        DataGridRow dgr = FindParent<DataGridRow>(sender as DataGridCell);
        dgr.Background = new SolidColorBrush(Colors.White);
    }

And this is the helper method to get the parent:

    public static T FindParent<T>(DependencyObject child) where T : DependencyObject
    {
        //get parent item
        DependencyObject parentObject = VisualTreeHelper.GetParent(child);

        //we've reached the end of the tree
        if (parentObject == null) return null;

        //check if the parent matches the type we're looking for
        T parent = parentObject as T;
        if (parent != null)
            return parent;
        else
            return FindParent<T>(parentObject);
    }

It's not MVVM, but taking into consideration that we're just working with the View elements .. i think this time it's not a must. So basically, on first selection you color the row, and on lost focus turn back to white the previous one and change color for the new selection.

This works and is as MVVM as it gets. For better readability I used ExpressionConverter which is an amaizing way to make XAML more readable but more error prone. I also made a couple of changes to it to support mutlibindings but that's offtopic, you get the basic idea from the code: get the data context from the row and the CurrentCell property of the grid and compare if they are the same.

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridRow}">
        <Style.Triggers>
            <DataTrigger Value="True">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{amazing:ExpressionConverter 'x[0] == x[1]'}">
                        <Binding RelativeSource="{RelativeSource Self}" Path="DataContext"></Binding>
                        <Binding ElementName="Grid" Path="CurrentCell" Converter="{amazing:ExpressionConverter 'x.Item'}"></Binding>
                    </MultiBinding>
                </DataTrigger.Binding>
                <Setter Property="Background" Value="Red"></Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</DataGrid.Resources>

I found a great solution for this on MSDN. Linking to my answer on a similar question:

Highlight row when SelectionUnit is set to Cell

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM