ebelair ebelair - 3 months ago 29
C# Question

DataGrid checkall not working

Hi have a Datagrid with rowCheckBoxes and an header checkbox for checking all.

The header checkbox bind a method in MainViewModel who will update the property of my model data to true. But the checkboxes are still unchecked.

<DataGrid AutoGenerateColumns="False" x:Name="grdLignes" HorizontalAlignment="Stretch" Margin="0,0,0,0"
VerticalAlignment="Stretch" CanUserAddRows="False" CanUserDeleteRows="False" Grid.ColumnSpan="2"
ItemsSource="{Binding CmLignes, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=hasLink, Mode=OneTime}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<CheckBox Command="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=DataContext.ToggleCheckAll}" CommandParameter="{Binding IsChecked, RelativeSource={RelativeSource Self}}"/>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="rowCheck" VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding Path=hasLink, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Ref Mag" Binding="{Binding Path=refMag}" IsReadOnly="True"/>
<DataGridTextColumn Header="Ref Fourn" Binding="{Binding Path=refFourn}"/>
<DataGridTextColumn Header="Désignation" Binding="{Binding Path=design}"/>
<DataGridTextColumn Header="Quantité" Binding="{Binding Path=qte, StringFormat=N2}"/>
<DataGridTemplateColumn Header="Fournisseur">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!--<ComboBox ItemsSource="{Binding FournList, RelativeSource={RelativeSource AncestorType=Window}}" SelectedItem="{Binding Path=fourn}"/>-->
<ComboBox ItemsSource="{Binding Path=fournList}" SelectedItem="{Binding Path=selectedFourn, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Fourn princ" Binding="{Binding Path=fournPrinc}" IsReadOnly="True"/>
<DataGridTextColumn Header="Pièce" Binding="{Binding Path=numPiece}" IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>


Then the MainViewModel:

public class MainViewModel : INotifyPropertyChanged
{
private ContremarqueRepository cmRepos;

private ObservableCollection<Contremarque> cmLignes;
public ObservableCollection<Contremarque> CmLignes
{
get { return cmLignes; }
set
{
cmLignes = value;
OnPropertyChanged("CmLignes");
}
}
public ICommand ToggleCheckAll { get; set; }
public MainViewModel()
{
Collection<Contremarque> cms = cmRepos.getAll(doPiece);
CmLignes = new ObservableCollection<Contremarque>(cms);

ToggleCheckAll = new Command(ActionToggleCheckAll);
}

private void ActionToggleCheckAll(object param)
{
bool isChecked = (bool)param;
if (isChecked)
{
foreach (Contremarque contremarque in CmLignes)
{
contremarque.hasLink = true;
}
}

OnPropertyChanged("CmLignes");
}
}


This is the Contremarque class:

public class Contremarque
{
public bool hasLink { get; set; }
public string refMag { get; set; }
public string refFourn { get; set; }
public string design { get; set; }
public double qte { get; set; }
public string fournPrinc { get; set; }
public List<string> fournList { get; set; }
public string selectedFourn { get; set; }
public string numPiece { get; set; }

public int dlNo;

public override string ToString()
{
string str = string.Empty;
foreach (var prop in this.GetType().GetProperties())
{
str += string.Format("{0} = {1} ", prop.Name, prop.GetValue(this, null));
}

return str;
}
}


The propertyChanged should update the state of my checkboxes isn't it?

Answer

Your class Contremarque should implement INotifyPropertyChanged and property hasLink should look like that:

public class Contremarque : INotifyPropertyChanged
{
    private bool _hasLink;      
    public bool hasLink 
    {
        get { return _hasLink; }
        set
        {
            _hasLink= value;
            OnPropertyChanged();
        }
    }
    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }           
    }
}