WPF TextBox с проверкой теряет ErrorTemplate
У меня есть проблема, очень похожая на эти:
Проблема с проверкой WPF (IDataErrorInfo) и фокусировкой вкладок
TextBox с проверкой теряет ErrorTemplate при смене вкладки
AdornerDecorator
сделать трюк в том же экземпляре Window
, но когда Window
перезагружается, и я переключаюсь на TabItem
содержащий TextBox
по ошибке, ErrorTemplate
больше не будет
<Window x:Class="Views.MyWindowView">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TabControl HorizontalAlignment="Stretch"
Height="Auto"
VerticalAlignment="Top"
Width="Auto"
SelectionChanged="TabItemChanged"
Name="MyTabControl">
<!-- Below, AdornerDecorator are added for the following reason:
the Validation.Error cues are painted in the Adorner Layer.
When tabs are switched, that layer is discarded. -->
<!-- The view 1 tab.-->
<TabItem Header="{Resx tab1_Header}"
Name="Tbi1">
<AdornerDecorator>
<vw:MyView1 DataContext="{Binding}"/>
</AdornerDecorator>
</TabItem>
<!-- The view 2 tab.-->
<TabItem Header="{Resx tab2_Header}"
Name="Tbi2">
<AdornerDecorator>
<vw:MyView2 DataContext="{Binding}"/>
</AdornerDecorator>
</TabItem>
</TabControl>
...
Я попытался повторить проверку в коде на TabControl
SelectionChanged
не работал.
Любая идея?
2 ответа
Собираем кусочки головоломки
AdornerLayer представляет поверхность для рендеринга украшений. Как AdornerLayer
обычно служит целому представлению, а не одному элементу управления, некоторые контейнеры реализуют их по умолчанию.
Adorner это обычай FrameworkElement
это связано с UIElement
, Украшения оказываются в AdornerLayer
, которая представляет собой поверхность рендеринга, которая всегда находится над украшенным элементом или набором украшенных элементов.
Таким образом, в этом случае рекламодатель (красный прямоугольник) связан с TextBox
, но отображается в слое поверх TextBox
,
Украшение (например, в случае ошибки проверки) выполняется путем вызова статического метода GetAdornerLayer
чтобы получить AdornerLayer
объект для UIElement
быть украшенным.
Достаточно теории
изменения TabItems
отбрасывает AdornerLayer
, в результате чего рекламодатель не рисуется. 2 исправления:
\ Ручной способ, предложенный DRapp:
<XAML for MyView1>
<AdornerDecorator>
...
</AdornerDecorator>
</close XAML for MyView1>
Конечно, если есть другой контейнер, реализующий AdornerLayer
между AdornerDecorator
и TextBox
(в визуальном дереве), это не поможет. Так явное AdornerDecorator
должен быть последним, оборачивая TextBox
,
<XAML for MyView1>
<Grid>
...
<GroupBox>
<AdornerDecorator>
<Grid>
...
<TextBox ... />
</Grid>
</AdornerDecorator>
</GroupBox>
</Grid>
</close XAML for MyView1>
Второе решение (которое я предпочитаю) сбрасывать ErrorTemplate каждый раз, когда TextBox
становится видимым При этом отсутствие AdornerLayer
получает замечен и исправлен.
<UserControl.Resources>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsVisible" Value="true">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
Я видел некоторые странные вещи с WPF и предложил бы это предложение. В соответствии с другими публикациями, на которые вы ссылались и пытались применить их здесь, оборачивая свой вид декоратором adorner, перенесите обтекатель adorner прямо на свою XAML-страницу "MvView1".
Из вашего существующего...
<AdornerDecorator>
<vw:MyView1 DataContext="{Binding}"/>
</AdornerDecorator>
изменить на...
<vw:MyView1 DataContext="{Binding}"/>
И в
<XAML for MyView1>
<AdornerDecorator>
[wrapping is within the view... then the rest of the view...]
</AdornerDecorator>
</close XAML for MyView1>
Я заметил подобное, например, применение видимости элементов управления, что если некоторые вещи на одном уровне не работают, на другом - нет. Никогда не нашел точный образец, хотя.