Search code examples
wpfdatagrid

How to set the margin in a style according to a value in the source object?


I am using WPF .NET Core 3.0 . I have a datagrid, and I want to use a style to set the margin of the rows according to the value of a property in the source object. I am trying this code:

<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellStyle">
    <Setter Property="Background" Value="LightGray"/>
    <Setter Property="Margin" Value="-1,10,0,0"/>
    <Setter Property="FontSize" Value="9"/>
    <Setter Property="Height" Value="18"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Grid Background="{TemplateBinding Background}" >
                    <Border Padding="9,0,0,0">
                        <ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    </Border>
                </Grid>

                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding Path=MyPropertyInSource, RelativeSource={RelativeSource Self}}" Value="-1">
                        <Setter Property="Margin" Value="-1,-30,0,0"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>



<DataGrid Name="MyDataGrid"
              ItemsSource="{Binding Data}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Title" Binding="{Binding MyPropertyTitle}" Width="29.7cm"
                            CellStyle="{StaticResource DataGridCellStyle}"/>
    </DataGrid.Columns>
</DataGrid>

In the style, in the data trigger, I try to bind the property of the source in and if it is equal to -1, set a top margin to -30, if not, use the default margin that is set with a value or 10. I have checked that the source object has the -1 value in the property, but the data trigger is not thrown.

I would like to use a style, because I have some data-grid that use the same logic and I would like to reuse the style if it is possible to avoid to have to copy every time.

EDIT: I will add more code with the classes that are used as data source.

<DataGrid Name="MainDataGrid" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,0,0,0" Grid.Column="0" Grid.Row="0"
            Style="{StaticResource DataGridMainStyle}"
            RowStyle="{DynamicResource DataGridMainRowStyle}"
            ItemsSource="{Binding Data}">
    <DataGrid.Columns>
    </DataGrid.Columns>

    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <DataGrid Name="DetailsDataGrid"
                          Style="{StaticResource DataGridDetailsStyle}"
                          CellStyle="{StaticResource DataGridDetailsCellStyle}"
                          ItemsSource="{Binding MyCollectionDetails}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Title" Binding="{Binding DatailsProperty}" Width="29.7cm"/>
                </DataGrid.Columns>
            </DataGrid>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>





<Style x:Key="DataGridMainStyle" TargetType="{x:Type DataGrid}">
    <Setter Property="HeadersVisibility" Value="Column"/>
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="VerticalGridLinesBrush" Value="Black"/>
    <Setter Property="HorizontalGridLinesBrush" Value="Black"/>
</Style>




<Style x:Key="DataGridDetailsStyle" TargetType="{x:Type DataGrid}">
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>



<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellStyle">
    <Setter Property="Background" Value="LightGray"/>
    <Setter Property="Margin" Value="-1,10,0,0"/>
    <Setter Property="FontSize" Value="9"/>
    <Setter Property="Height" Value="18"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Grid Background="{TemplateBinding Background}" >
                    <Border Padding="9,0,0,0">
                        <ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    </Border>
                </Grid>

                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding Path=MyPropertyInSource, RelativeSource={RelativeSource Self}}" Value="-1">
                        <Setter Property="Margin" Value="-1,-30,0,0"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>








public class Datos : BaseViewModel
{
    private ObservableCollection<Details> _details = new ObservableCollection<Details>();
    public ObservableCollection<Details> Details
    {
        get { return _details; }
        set
        {
            _details = value;
            base.RaisePropertyChangedEvent(nameof(Details));
        }
    }
}




public class Details
{
    private MyType _myPrerty;
    public MyType MyPrerty
    {
        get { return _myPrerty; }
        set
        {
            _myPrerty = value;
            base.RaisePropertyChangedEvent(nameof(MyPrerty));
        }
    }
}




private ObservableCollection<Data> _data = new ObservableCollection<Data>();
public ObservableCollection<Datos> Data
{
    get { return _data; }
    set
    {
        _data = value;
        base.RaisePropertyChangedEvent(nameof(Data));
    }
}

Solution

  • Remove RelativeSource={RelativeSource Self} from the trigger since the DataContext of the cell is the current item in the ItemsSource by default:

    <ControlTemplate TargetType="{x:Type DataGridCell}">
        <Grid Background="{TemplateBinding Background}" >
            <Border Padding="9,0,0,0">
                <ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center"/>
            </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=MyPropertyInSource}" Value="-1">
                <Setter Property="Margin" Value="-1,-30,0,0"/>
            </DataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>