Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding a DataTrigger to the IsChecked property of a checkbox

I believe what I'm trying to do is "simple" enough, so I'm probably just missing something obvious.

In a DataGrid, I am trying to bind a CheckBox so that when it is checked, the Background color of its row will change. Every row has a CheckBox. I am basically implementing my own select-multiple-rows functionality (it's a product requirement, don't ask), and I have everything else working but this visual indication of a selected row.

I've read this question but where I lack my answer is what exactly to put as "BooleanPropertyOnObjectBoundToRow". I've also looked at this question and tried messing with a RelativeSource but with no luck.

I create my grid in my code-behind, but here is my current style used for rows (which has my DataTrigger defined):

<Style x:Key="MyRowStyle" TargetType="DataGridRow">
      <Style.Triggers>
           <DataTrigger Binding="{Binding IsChecked}" Value="True">
               <Setter Property="Background" Value="Blue"/>
           </DataTrigger>
      </Style.Triggers>
</Style>

Now in my code-behind, I create my DataGridTemplateColumn and use a Factory to create my checkboxes, and here is my Binding-relevant code:

Binding checkBinding = new Binding("IsChecked");
checkBinding.Mode = BindingMode.OneWayToSource;
RelativeSource relativeSource = new RelativeSource();
relativeSource.AncestorType = typeof(DataGridRow);
relativeSource.Mode = RelativeSourceMode.FindAncestor;
checkBinding.RelativeSource = relativeSource;
factory.SetBinding(CheckBox.IsCheckedProperty, checkBinding);

What may be of interest is the fact that I set the ItemsSource of my DataGrid to a DataTable, but my CheckBox column does NOT have a corresponding column in the DataTable. I simply add the template column separately, maybe this lack of underlying storage is affecting this?

In any case if you need any more info, please let me know. Thanks!

like image 322
WPFNewbie Wannabe Avatar asked Mar 28 '12 20:03

WPFNewbie Wannabe


1 Answers

Here's an example that works for me using C# classes, not a DataSet.

Xaml

<Page.Resources>
    <Style x:Key="RowStyle" TargetType="{x:Type DataGridRow}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" Value="True">
                <Setter Property="Background" Value="Blue"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Page.Resources>

<Page.DataContext>
    <Samples:DataGridRowHighlightViewModels/>
</Page.DataContext>

<Grid>
    <DataGrid ItemsSource="{Binding Items}" RowStyle="{StaticResource RowStyle}" CanUserAddRows="False" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridCheckBoxColumn Header="Selected" Binding="{Binding IsChecked}"/>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

C#

public class DataGridRowHighlightViewModels
{
    public DataGridRowHighlightViewModels()
    {
        Items = new List<DataGridRowHighlightViewModel>
                    {
                        new DataGridRowHighlightViewModel {Name = "one"},
                        new DataGridRowHighlightViewModel {Name = "two"},
                        new DataGridRowHighlightViewModel {Name = "three"},
                        new DataGridRowHighlightViewModel {Name = "four"},
                    };
    }
    public IEnumerable<DataGridRowHighlightViewModel> Items { get; set; } 
}

// ViewModelBase and Set() give INotifyPropertyChanged support (from MVVM Light)
public class DataGridRowHighlightViewModel : ViewModelBase 
{
    private bool _isChecked;
    public bool IsChecked
    {
        get { return _isChecked; }
        set { Set(()=>IsChecked, ref _isChecked, value); }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set { Set(()=>Name, ref _name, value); }
    }
}
like image 190
Phil Avatar answered Oct 31 '22 14:10

Phil