【问题标题】:Wpf dynamic resource lookup for Validation.ErrorTemplateValidation.ErrorTemplate 的 Wpf 动态资源查找
【发布时间】:2016-01-26 14:15:36
【问题描述】:

在我的 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 周围获得 RED 边框?

【问题讨论】:

    标签: c# wpf resourcedictionary dynamicresource


    【解决方案1】:

    您看到的行为非常好。背后的原因:

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

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

    【讨论】:

    • 我的主要目的是单独参数化ErrorTemplates。我试图使用本地资源来做到这一点,但忘记了装饰者的行为。感谢您的澄清
    【解决方案2】:

    我已经实现了一个绑定转换器,它可以从 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 不同,它不会立即发生。通过绑定解析的静态资源允许对每个实例进行自定义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      相关资源
      最近更新 更多