-1

在我的 App.xaml 中,我为 定义了一个资源Validation.ErrorTemplate,它取决于动态BorderBrush资源。我打算BorderBrush在我拥有的每个窗口以及窗口内的不同块中定义唯一的。

<!--validation error template-->
<ControlTemplate x:Key="NonValid">
    <Border BorderBrush="{DynamicResource BorderBrush}" BorderThickness="2" Margin="5">
        <AdornedElementPlaceholder x:Name="ui"/>
    </Border>
</ControlTemplate>

而这个来证明我的问题(也有动态画笔资源)

<!--test template-->
<ControlTemplate x:Key="ButtonRes" TargetType="Button">
    <Border BorderBrush="{DynamicResource BorderBrush}" BorderThickness="2" Background="Khaki">
        <ContentPresenter />
    </Border>
</ControlTemplate>

现在我使用这些模板的窗口可以解析普通模板的画笔资源,但不能解析Validation.ErrorTemplate

它看起来如何

<Window x:Class="MyApp.MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Test" Height="300" Width="300">
    <Window.Resources>
        <!-- window overrides resource-->
        <SolidColorBrush x:Key="BorderBrush" Color="Blue"/>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!-- button can see window resource-->
        <Button Template="{StaticResource ButtonRes}"/>        

        <Grid Grid.Row="1">
            <Grid.Resources>
                <!-- grid overrides resource-->
                <SolidColorBrush x:Key="BorderBrush" Color="Red"/>
            </Grid.Resources>

            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <!-- button can see grid resource-->
            <Button Template="{StaticResource ButtonRes}"/>

            <!-- errorTemplate CAN     SEE window resource-->
            <!-- errorTemplate CAN NOT SEE grid   resource-->
            <TextBox Grid.Row="1" VerticalAlignment="Center" Text="{Binding Name}" 
                 Validation.ErrorTemplate="{StaticResource NonValid}"/>
        </Grid>
    </Grid>
</Window>

我应该怎么做才能在 TextBox 周围获得红色边框?

4

2 回答 2

3

您看到的行为非常好。背后的推理:

Validation.ErrorTemplate放置在adorner layer窗口中,该窗口位于窗口中所有其他控件的上方。这就是为什么它无法查看在网格级别定义的资源并使用窗口资源解析引用的原因。

如果您想动态解决它,唯一可能的解决方案是在窗口资源中声明它或使用静态分配。

于 2016-01-26T15:25:48.487 回答
0

我已经实现了一个绑定转换器,它可以从 Validation.ErrorTemplate 中找到资源。它需要一个 FrameworkElement 实例(显示 ErrorTemplate 的元素)和资源键:

public class ResourceProviderConverter : IValueConverter
{
    /// <summary>
    /// Returns requested resource from element visual tree
    /// </summary>
    /// <param name="value">Should contain FrameworkElement which has access to resource</param>
    /// <param name="targetType"></param>
    /// <param name="parameter">Resource key</param>
    /// <param name="culture"></param>
    /// <returns>Resource value if resource was found</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {            
        if (parameter != null && (value is FrameworkElement element))
        {
            var result = element.TryFindResource(parameter);
            if (result != null)
                return result;
        }

        return Binding.DoNothing;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

修改错误模板:

<local:ResourceProviderConverter x:Key="ResourceProvider"/>

<ControlTemplate x:Key="NonValid">
    <Border BorderBrush="{Binding ElementName=ui, Path=AdornedElement, 
                                  Converter={StaticResource ResourceProvider}, 
                                  ConverterParameter='BorderBrush', 
                                  FallbackValue={x:Static Brushes.Purple}}" 
            BorderThickness="2" Margin="5">
        <AdornedElementPlaceholder x:Name="ui"/>
    </Border>
</ControlTemplate>

每次显示 ErrorTemplate 时都会触发绑定和转换器。因此可以更新资源并查看 ErrorTemplate 的变化。但与 DynamicResource 不同,它不会立即发生。通过绑定解决的静态资源允许对每个实例进行自定义。

于 2020-05-17T16:47:02.487 回答