2016-12-15 8 views
4

У меня есть вопрос, очень похожий на них:WPF TextBox с проверкой теряет ErrorTemplate

Issue with WPF validation(IDataErrorInfo) and tab focusing

TextBox with validation loses ErrorTemplate on tab change

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> 

...

Я пытался RETRIGGER проверки в отделенном коде на TabControlSelectionChanged, не работает.

Любая идея?

+0

«Когда окно перезагружается»? Что это значит? Почему ваша перезагрузка окна? Как перезагрузка? – Will

+1

Это модальное диалоговое окно. Он может быть открыт и закрыт много раз. Это то, что я подразумеваю под «перезагрузкой». – CTZStef

+0

Вы скрываете это и показываете его, а не разрушаете его между ними? – Will

ответ

3

Собирая кусочки головоломки

AdornerLayer представляет собой поверхность для рендеринга графических элементов. Как AdornerLayer обычно служит весь вид, а не только один элемент управления, некоторые контейнеры реализуют их по умолчанию.

adorner является обычным FrameworkElement, который связан с UIElement. Декодеры отображаются в AdornerLayer, который является поверхностью рендеринга, которая всегда находится поверх украшенного элемента или коллекции украшенных элементов.

Так что в этом случае adorner (красный прямоугольник) привязан к TextBox, но отображается в слое поверх TextBox.

Украшать (например, в случае ошибки проверки) выполняется путем вызова статического метода GetAdornerLayer, чтобы получить AdornerLayer объект для UIElement быть украшены.

Достаточно теории

Изменение TabItems отбрасывается AdornerLayer, в результате чего в Adorner не втягиваются. 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> 
2

Я видел некоторые странные вещи с WPF и предлагал это предложение. На другие сообщения, на которые вы ссылались, и попытались применить их здесь, чтобы обернуть свой взгляд с помощью декоратора-декоратора, переместите обертывание рекламодателя непосредственно на страницу «MvView1» XAML.

из существующих ...

<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> 

Я заметил, похоже, такие как применяющим видимость контроля, если не указано некоторые вещи находятся на одном уровне, они работают, а в другом - нет. Тем не менее, он не нашел точного рисунка.

+0

К сожалению, это тоже не сработало. – CTZStef

+1

@CTZStef Некоторые элементы управления (например, [Groupbox] (http://stackoverflow.com/a/33911629/4838058)), похоже, нарушают поток и требуют, чтобы «AdornerDecorator» был помещен внутри. В качестве быстрой проверки попробуйте обернуть «TextBox». – Funk

+0

@Funk обертывание TextBox в AdornerDecorator работает; пожалуйста, создайте ответ, и я с радостью его приму. Если бы вы могли добавить несколько подробностей об этой магии, это было бы здорово. Благодаря! – CTZStef

 Смежные вопросы

  • Нет связанных вопросов^_^