带有MVVM的WPF DataGrid行样式

本文关键字:样式 DataGrid WPF MVVM 带有 | 更新日期: 2023-09-27 18:21:29

我有一个DataGrid,如果ViewModel类的某个属性设置为true,我想在其中更改行边界颜色或背景。我在将DataTrigger绑定到行源项(ViewModel)属性时遇到问题。在这种情况下,我希望绑定到ViewModel属性IsExpired。不幸的是,它不允许我在运行时抛出和异常。如有任何帮助,我们将不胜感激。

public class ViewModel 
{
    public uint Id { get; private set;}
    public string Symbol { get; private set;}
    public bool IsExpired { get; private set;}
}
public class WindowViewModel : PropertyChangedNotifier
{
    public ObservableCollection<ViewModel> ViewModels { get; private set;}
    private DateTime _timestamp;
    public DateTime TimeStamp
    {
        get { return _timestamp; }
        set 
        {
            _timestamp = value;
            OnPropertyChanged("TimeStamp");
        }
    }
}
<Grid x:Name="Layout" d:DataContext="{StaticResource DesignerViewModel}" DataContext="{Binding}">
    <Grid.RowDefinitions>
        <RowDefinition Height="30"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0" Orientation="Horizontal">
        <TextBlock Text="Accounts" VerticalAlignment="Center" Margin="5"/>
        <ComboBox x:Name="AccountsComboBox" ItemsSource="{Binding Accounts}"  DisplayMemberPath="ClearingNumber" Width="125" 
                  HorizontalAlignment="Left" Margin="5" IsEditable="False" IsReadOnly="True" Style="{StaticResource AccountComboBoxStyle}"/>
        <Button x:Name="LoadPositionsButton" Content="Load" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center" Width="50" Click="LoadPositionsButtonOnClick"/>
        <TextBlock x:Name="TimeStampTextBlock" HorizontalAlignment="Right" Margin="5" Width="150" Text="{Binding LastUpdate, Converter={StaticResource TimeStampConverter}}"/>
    </StackPanel>
    <DataGrid Grid.Row="1" ItemsSource="{Binding ViewModels}" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False"
              CanUserResizeRows="False" CanUserSortColumns="False" AutoGenerateColumns="False" HeadersVisibility="Column">
        <DataGrid.RowStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsExpired}" Value="True">
                        <Setter Property="BorderBrush" Value="Red"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>    
        <!-- ... -->
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Account">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="vm:ViewModel">
                        <TextBlock Text="{Binding Account}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <!--<DataGridTemplateColumn Header="Exch">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="vm:ViewModel">
                        <TextBlock Text="{Binding ExchangeCode}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>-->
            <DataGridTemplateColumn Header="Symbol">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="vm:ViewModel">
                        <TextBlock Text="{Binding Symbol}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Description">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="vm:ViewModel">
                        <TextBlock Text="{Binding Description}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Maturity">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate DataType="vm:ViewModel">
                        <TextBlock Text="{Binding MaturityMonthYear}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
       <DataGrid.Columns>
    </DataGrid>
</Grid>

带有MVVM的WPF DataGrid行样式

首先应该为ViewModel类实现INotifyPropertyChanged接口。这与你在WindowViewModel课上的写作方式类似。然后将自动属性IsExpired更改为:

public bool IsExpired
{
    get { return _isExpired; }
    set
    {
        _isExpired = value;
        OnPropertyChanged("IsExpired");
    }
}

其次,如果您想更改某个列的样式,您应该更改列的CellStyle属性:

<DataGrid Grid.Row="1" ItemsSource="{Binding ViewModels}" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False"
  CanUserResizeRows="False" CanUserSortColumns="False" AutoGenerateColumns="False" HeadersVisibility="Column">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="HeaderName" >
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Symbol}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellStyle>
                <Style TargetType="{x:Type DataGridCell}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsExpired}" Value="True">
                            <Setter Property="BorderBrush" Value="Red"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTemplateColumn.CellStyle>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
    <!-- ... -->
</DataGrid>

如果您想更改数据网格行的样式,您应该使用Template属性,例如:

<DataGrid Grid.Row="1" ItemsSource="{Binding ViewModels}" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False"
    CanUserResizeRows="False" CanUserSortColumns="False" AutoGenerateColumns="False" HeadersVisibility="Column">
    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridRow}">
                        <Border x:Name="DataGridRowBorder"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            SnapsToDevicePixels="True">
                            <!-- Row template -->
                            <Grid>
                                <TextBlock Text="{Binding Path=Symbol}" />
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <DataTrigger Binding="{Binding IsExpired}" Value="True">
                                <Setter TargetName="DataGridRowBorder" Property="BorderBrush" Value="Red"/>
                                <Setter TargetName="DataGridRowBorder" Property="BorderThickness" Value="1"/>
                            </DataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.RowStyle>
    <!-- ... -->
</DataGrid>