netmajor
netmajor

Reputation: 6585

Style data trigger to color row on datagrid

I have code:

    <UserControl x:Class="MediaNet.View.MusicWindow.MusicWindow"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:musicVM="clr-namespace:MediaNet.ViewModel.MusicWindowViewModel"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
                 mc:Ignorable="d"
                 d:DesignHeight="350" d:DesignWidth="557">
        <UserControl.DataContext>
            <musicVM:MusicWindowViewModel />
        </UserControl.DataContext>
        <UserControl.Resources>
            <musicVM:TimeSpanConverter x:Key="TimeSpanConverter" />
            <musicVM:CurrentSongIndexConverter x:Key="CurrentSongIndexConverter" />
        </UserControl.Resources>
             <DataGrid Grid.Row="1" AutoGenerateColumns="True" VerticalAlignment="Top"  ItemsSource="{Binding Path=MusicItems}" SelectedIndex="{Binding Path=SelectedIndex}" >
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=CurrentSongIndex, Converter={StaticResource CurrentSongIndexConverter}, RelativeSource={RelativeSource Mode=Self}}"  Value="True">
                        <Setter Property="Background"  Value="Red"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.ContextMenu>
            <ContextMenu >
                <MenuItem Command="Delete">
                    <MenuItem.Icon>
                        <Image  />
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="Song options">
                    <MenuItem Header="Play to this song" Command="{Binding SetStopPositionCommand}"  />
                </MenuItem>
            </ContextMenu>
        </DataGrid.ContextMenu>
    </DataGrid>

MusicItem is

ObservableCollection<Song> 

view model:

namespace MediaNet.ViewModel.MusicWindowViewModel
{
    public class MusicWindowViewModel : INotifyPropertyChanged, IDisposable
    {
 #region CurrentSongIndex
        private int _currentSongIndex;
        public int CurrentSongIndex
        {
            get { return _currentSongIndex; }
            set
            {
                _currentSongIndex = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("CurrentSongIndex"));
                }
            }
        }
        #endregion
 }
}

Converter:

namespace MediaNet.ViewModel.MusicWindowViewModel
{
    class CurrentSongIndexConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int CurrentSongIndex = (int)value;
            return CurrentSongIndex > 0;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

This should set background color to row in data grid, but now work. Haw can I tell trigger to which row should it change background ?

Upvotes: 1

Views: 4001

Answers (1)

sellmeadog
sellmeadog

Reputation: 7517

The Style will be applied to every row in the DataGrid. The Binding in the DataTrigger should be relative to the DataContext of each row. This ensures that for each row, the binding will be evaluated.

Please clarify/verify the following:

  • How exactly does this "not work"? Are no rows being highlighted, all rows being highlighted?
  • Does your converter work? Have you verified that it is returning true when expected to properly evaluate the trigger binding?

UPDATE

Looking at your updated code sample, the problem is that CurrentSongIndex is not in the DataContext in each DataGridRow. Per your XAML, you have ItemsSource="{Binding Path=MusicItems}".

When each row of the grid is databound, DataGridRow.DataContext is set to the corresponding Song. When that happens, the binding no longer has access to the CurrentSongIndex because it's part of the MusicWindowViewModel.

Try changing your data trigger binding to something like this:

{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.CurrentSongIndex, Converter={StaticResource CurrentSongIndexConverter}}

This will force the binding to look at the DataContext of the window who's DataContext is the MusicWindowViewModel which contains the CurrentSongIndex property.

Upvotes: 1

Related Questions