隐藏控件时隐藏验证装饰

时间:2011-01-31 19:31:52

标签: wpf mvvm adorner

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

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

2 个答案:

答案 0 :(得分:7)

ControlTemplate的默认Validation.ErrorTemplate有一个AdornedElementPlaceholder,而AdornedElement则会引用其<ControlTemplate> <Border BorderBrush="Red" BorderThickness="1"> <AdornedElementPlaceholder /> </Border> </ControlTemplate> 。看起来像这样

Border

从此处可以将AdornedElementPlaceholder.AdornedElement的可见性与Control的可见性绑定,以链接其可见性。然后,我们将具有此问题的所有Validation.ErrorTemplate设为使用此<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。这是一个例子

Xaml

Parent

<强>更新
要在绑定中引用父TextBox,您可以

1.对于特定控件,您可以使用StackPanel属性

向上走逻辑树

示例:如果UserControl位于<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> 中的ResourceDictionary,我们可以使用Parent.Parent

引用它
Border

2.对于更动态的方法,您可以使用带有代码隐藏文件的UserControl,其中您可以使用<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> 的Loaded事件。在其中,您沿着可视​​树向上查找父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; } } 并将其用作绑定的来源

ValidationErrorTemplateDictionary.xaml

<UserControl ...>
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ValidationErrorTemplateDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel>
        <TextBox ...
                 Validation.ErrorTemplate="{StaticResource ValidationErrorTamplate3}">

ValidationErrorTemplateDictionary.xaml.cs

{{1}}

您的UserControl

{{1}}

答案 1 :(得分:0)

我必须解决这个问题,因为可见性和不透明度。

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

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

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

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

或者,这是一个很好的堆栈: How exactly do Attached Properties work in WPF?