4

在 WPF 中,如何在隐藏控件时隐藏验证错误模板装饰(默认为红色框)?当我隐藏我的控件(以方便在视图之间切换)时,错误装饰仍然存在。

更难的是,我如何使用 MVVM 做到这一点?

4

2 回答 2

7

的默认值ControlTemplateValidation.ErrorTemplate一个AdornedElementPlaceholderwhich 又引用了它的AdornedElement. 看起来像这样

<ControlTemplate>
    <Border BorderBrush="Red" BorderThickness="1">
        <AdornedElementPlaceholder />
    </Border>
</ControlTemplate>

从这里可以将 Visibility 绑定到 VisibilityBorderAdornedElementPlaceholder.AdornedElement链接它们的 Visibility。然后我们让所有Control有这个问题的 's 使用这个Validation.ErrorTemplate而不是默认的。这是一个例子

Xaml

<Window.Resources>
    <ControlTemplate x:Key="ValidationErrorTamplate">
        <Border Visibility="{Binding ElementName=placeHolder,
                                     Path=AdornedElement.Visibility}"
                BorderBrush="Red"
                BorderThickness="1">
            <AdornedElementPlaceholder x:Name="placeHolder"/>
        </Border>
    </ControlTemplate>
</Window.Resources>
<TextBox ...
         Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate}">

更新
要在绑定中引用父级UserControl,您可以

1.对于特定控件,您可以使用Parent属性向上走逻辑树

示例:如果TextBox位于 aStackPanel中,UserControl我们可以使用 Parent.Parent 引用它

<UserControl ...>
    <StackPanel>
        <TextBox ...
                 Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate2}">

<ControlTemplate x:Key="ValidationErrorTamplate2">
    <Border Visibility="{Binding ElementName=placeHolder,
                                 Path=AdornedElement.Parent.Parent.Visibility}"
            BorderBrush="Red"
            BorderThickness="1">
        <AdornedElementPlaceholder x:Name="placeHolder"/>
    </Border>
</ControlTemplate>

2.对于更动态的方法,您可以使用ResourceDictionary带有代码隐藏文件的代码,您可以在其中使用 Loaded 事件Border。在其中,您沿着可视​​化树查找父级UserControl并将其用作 Binding 的源

ValidationErrorTemplateDictionary.xaml

<ResourceDictionary x:Class="ValidationErrorVisibility.ValidationErrorTemplateDictionary"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ControlTemplate x:Key="ValidationErrorTamplate3">
        <Border BorderBrush="Red"
                BorderThickness="1"
                Loaded="ValidationAdorner_Loaded">
            <AdornedElementPlaceholder/>
        </Border>
    </ControlTemplate>
</ResourceDictionary>

ValidationErrorTemplateDictionary.xaml.cs

public partial class ValidationErrorTemplateDictionary
{
    private void ValidationAdorner_Loaded(object sender, RoutedEventArgs e)
    {
        Border adornedBorder = sender as Border;
        Binding visibilityBinding = new Binding("Visibility");
        UIElement adornedElement = ((AdornedElementPlaceholder)adornedBorder.Child).AdornedElement;
        UserControl parentUserControl = GetVisualParent<UserControl>(adornedElement);
        visibilityBinding.Source = parentUserControl;
        adornedBorder.SetBinding(Border.VisibilityProperty, visibilityBinding);
    }

    public static T GetVisualParent<T>(object childObject) where T : Visual
    {
        DependencyObject child = childObject as DependencyObject;
        while ((child != null) && !(child is T))
        {
            child = VisualTreeHelper.GetParent(child);
        }
        return child as T;
    }
}

您的用户控件

<UserControl ...>
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ValidationErrorTemplateDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel>
        <TextBox ...
                 Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate3}">
于 2011-01-31T23:51:26.273 回答
0

为了可见性和不透明度,我只需要解决这个问题。

我通过创建一个继承的附加属性来做到这一点,我将 ErrorTemplate 可见性和不透明度数据绑定到该属性。在父元素(淡入淡出/被折叠的实际元素)上,我只需将新附加属性分别绑定到可见性和不透明度。

此方法使用 WPF 的逻辑树和现有的属性值继承来解决问题,而无需隐藏代码,也无需模板了解可见性控制父级的具体知识。

事后看来,我本可以创建一个 FrameWorkElement 类型的附加属性,然后我可以使用它来绑定父元素上的任何属性。这种方法将涉及更少的绑定和更少的代码来实现,同时提供更多的灵活性。也许已经存在一个附加属性来让你做同样的事情。

您可以在此处阅读有关附加属性的所有信息:http: //msdn.microsoft.com/en-us/library/ms749011.aspx

或者,这是一个很好的堆栈: 附加属性在 WPF 中究竟是如何工作的?

于 2012-05-10T09:47:44.790 回答