Как установить красный фон для недопустимой ячейки как часть общего стиля сетки данных - PullRequest
1 голос
/ 20 октября 2019

Кажется, что общий подход к изменению внешнего вида недопустимых ячеек заключается в изменении ElementStyle и ElementEditingStyle определенного столбца сетки данных в XAML. Можно ли объединить эти стили вместе в общий стиль сетки данных? Чтобы при применении стиля к сетке данных стиль проверки также применялся к ячейкам?

Допустим, у меня есть правило проверки:

using System;
using System.Globalization;
using System.Windows.Controls;

namespace TestDataGridCellValidationStyle
{
    public class BookValidationRule : ValidationRule
    {
        public Type ValidationType { get; set; }
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            var stringValue = Convert.ToString(value);
            if (stringValue.Contains("Blade Runner"))
                return new ValidationResult(false, "Error");
            return new ValidationResult(true, null);
        }
    }
}

Если я применяю его кстолбец сетки, я могу использовать ElementStyle для отображения недопустимых ячеек сетки:

<Window x:Class="TestDataGridCellValidationStyle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestDataGridCellValidationStyle"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <x:Array x:Key="Books" Type="sys:String" 
            xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <sys:String>Alice in Wonderland</sys:String>
            <sys:String>Blade Runner</sys:String>
        </x:Array>
        <Style x:Key="CellElementStyle" TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="Background" Value="Red"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <DataGrid ItemsSource="{StaticResource Books}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Title" ElementStyle="{StaticResource CellElementStyle}">
                    <DataGridTextColumn.Binding>
                        <Binding Path=".">
                            <Binding.ValidationRules>
                                <local:BookValidationRule ValidatesOnTargetUpdated="True" />
                            </Binding.ValidationRules>
                        </Binding>
                    </DataGridTextColumn.Binding>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

И вот что я пытаюсь сделать (и это не работает):

<Window x:Class="TestDataGridCellValidationStyle.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestDataGridCellValidationStyle"
        Title="Window1" Height="450" Width="800">
    <Window.Resources>
        <x:Array x:Key="Books" Type="sys:String" 
            xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <sys:String>Alice in Wonderland</sys:String>
            <sys:String>Blade Runner</sys:String>
        </x:Array>
        <Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Grid>
                            <ContentPresenter x:Name="CellPresenter"/>
                            <Rectangle x:Name="InvalidStateRectangle" Opacity="0" IsHitTestVisible="False" Fill="Red"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Validation.HasError" Value="True">
                                <Setter TargetName="InvalidStateRectangle" Property="Opacity" Value="1"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="DataGridStyle" TargetType="DataGrid">
            <Setter Property="Background" Value="LightBlue"/>
            <Setter Property="CellStyle" Value="{StaticResource DataGridCellStyle}"/>
        </Style>
    </Window.Resources>
    <Grid>
        <DataGrid Style="{StaticResource DataGridStyle}" ItemsSource="{StaticResource Books}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Title">
                    <DataGridTextColumn.Binding>
                        <Binding Path=".">
                            <Binding.ValidationRules>
                                <local:BookValidationRule ValidatesOnTargetUpdated="True" />
                            </Binding.ValidationRules>
                        </Binding>
                    </DataGridTextColumn.Binding>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

У меня есть несколько сеток данных, определенных в разных местах, и я не хочу, чтобы каждая из них явно указывала стиль элемента. Есть ли способ поместить это в один стиль? Также я не хочу, чтобы этот стиль был глобальным (без ключа).

1 Ответ

1 голос
/ 21 октября 2019

Вы можете привязать к Validation.HasError вложенному свойству Content из DataGridCell следующим образом:

<Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Grid>
                    <Rectangle x:Name="InvalidStateRectangle" Opacity="0" IsHitTestVisible="False" Fill="Red"/>
                    <ContentPresenter x:Name="CellPresenter"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding Content.(Validation.HasError),
                                                RelativeSource={RelativeSource Self}}" Value="True">
                        <Setter TargetName="InvalidStateRectangle" Property="Opacity" Value="1"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...