Keith Jones
Keith Jones

Reputation: 85

WPF Datagrid Trigger doesn't work

I have datagrid bound to an ObservableCollection of items which do implement INotifyPropertyChanged. Just one column is editable. Another column is an image which I want to be automatically changed based on the value edited in the column. It doesn't work. It does refresh if I click on row header for example (sort), but not right after editing

<DataGrid ItemsSource="{Binding ItemRows,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" AutoGenerateColumns="False" 
                  CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="false">

            <DataGrid.Columns>
                <DataGridTextColumn Header="Editable" Binding="{Binding Editable, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image x:Name="imgComplete" Width="20" Height="20">
                                <Image.Style>
                                    <Style TargetType="{x:Type Image}">
                                        <Setter Property="Source" Value="{StaticResource imgCheckmarkOrange}" />
                                        <Style.Triggers>
                                            <DataTrigger Value="0" Binding="{Binding Editable,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
                                                <Setter Property="Source" Value="{StaticResource imgSadFace}"/>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </Image.Style>
                            </Image>                                                                                             
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>                        
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

EDIT: adding parts of my View model

I'm using FODY, my structure is pretty complex, so I am posting only what's related to datagrid source

[ImplementPropertyChanged]
public class MyViewModel 
{

....
    public ObservableCollection<StockOrderRow> ItemRows { get; set; } = new ObservableCollection<StockOrderRow>();

.....


}

This collection is loaded with data from the database on a change of another property

The Class "StockOrderRow"

    public class StockOrderRow : BaseEntity
    {
    public string Field1{ get; set; } = "";
    ...

    public int Editable { get; set; } = 0;



    }

And the class "BaseEntity"

public class BaseEntity: INotifyPropertyChanged
    {
    public string Id { get; set; }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {

        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

}

Upvotes: 1

Views: 582

Answers (1)

WPFGermany
WPFGermany

Reputation: 1649

I would recommend using a DataGridTemplateColumn for your Editable property. With this you can handle the Binding with PropertyChanged in your TextBox directly.

     <DataGridTemplateColumn>
         <DataGridTemplateColumn.CellTemplate>
             <DataTemplate>
                <TextBlock Text="{Binding Editable}" />
             </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
         <DataGridTemplateColumn.CellEditingTemplate>
             <DataTemplate>
                <TextBox Text="{Binding Editable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
             </DataTemplate>
         </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>

the second thing is that your ItemsClasses property Editable has to call the OnPropertyChange

public class StockOrderRow:BaseEntity
{
    public string Field1{ get; set; } = "";

    private int _editable = 0;
    public int Editable { 
        get { return _editable; } 
        set {
            if(value == _editable) return;

            // Debug.WriteLine("Editable set. OldVal: " + _editable + "; NewVal:" + value);
            _editable = value;
            OnPropertyChanged(nameof(Editable));
        } 
    }
}

Your DataTrigger doesn't need to Bind in Mode TwoWay

<Style.Triggers>
    <DataTrigger Value="0" Binding="{Binding Editable,UpdateSourceTrigger=PropertyChanged}">
        <Setter Property="Source" Value="{StaticResource imgSadFace}"/>
    </DataTrigger>
</Style.Triggers>

If this doesn't work I would start Debugging at the setter of Editable (and check, if the property is updated while typing in your TextBox...).

Upvotes: 1

Related Questions