Вопрос по wpf, tabcontrol, c#, styles, tabs – Стили ошибок WPF корректно отображаются только на видимой вкладке элемента управления вкладкой

16

У меня есть объект данных, используемый для хранения данных пользовательского интерфейса, который поддерживаетINotifyPropertyChanged а такжеIDataErrorInfo, Первоначально у меня были все элементы управления пользовательским интерфейсом, отображаемые в одном большом приложении WPF, и я с радостью видел ошибки, помеченные с помощью этого пользовательского стиля:

    
    
        
            
                
            
        

        
            
                
                    
                        
                        
                    
                
            
        
    

Сегодня я реорганизовал программу и решил распределить различные элементы управления пользовательским интерфейсом на несколько страницTabControl, Структура структуры, которую я использую для этого:


    
        
           [.. various Stack Panels, Groups and UI controls moved from original layout ..]
        
    
    
        
           [.. various Stack Panels, Groups and UI controls moved from original layout ..]
        
    

    ...
 

(Я используюAdornerDecorator как я уже видел в предыдущей программе, стиль ошибок не перерисовывается при смене вкладок. Я могу'Не помню, где я это видел, но это помогло мне.)

Теперь, когда я запускаю свою программу, стиль ошибок правильно отображается наTabItem который открывается при запуске программы, но не правильно отображает другой (скрытый)TabItems. Когда я выбираю (и раскрываю) один из тех,TabItems подсказка стиля ошибки установлена, но изображение значка ошибки не отображается.

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

Так что кажется, что я полностью упускаю что-то, что мешает стилям ошибок корректно отображаться на чем-то кроме открытой вкладки Item. Есть идеи?

Редактировать 3 сентября Изменено описание, чтобы поддержать лучшее понимание того, что я видел

Поговорим о Дежа ву в 2014

Это'С ноября 2014 года и сегодня у меня была эта глупая проблема WPF с шаблонами ошибок, которые не отображаются на элементах, представленных в контроллере вкладок. Что-то в глубине души наводит на мысль, что я видел эту проблему раньше. Итак, я Google, и первое, что появляется, это мой собственный вопрос с 2009 года!

На этот раз я вижу комментарий от dkl, который был добавлен после того, как я решил все в последний раз. Поэтому я попробовал его по-своему и использовал это решение (которое работало хорошо, и я нене нужно посыпать Adorner контроль над моими вкладками):


    
        
            
                
                
            
            
                
                    
                        
                            *
                            
                            
                                
                            
                        
                    
                
            
            
        
    

Ваш Ответ

3   ответа
1

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

Например:,

<resourcedictionary ...="">
    <!-- Add to the default style instead of replacing it -->
    <style targettype="TextBox" basedon="{StaticResource {x:Type TextBox}}">
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="Validation.HasError" Value="True" />
                    <Condition Property="IsVisible" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ValidationErrorTemplate}"/>
            </MultiTrigger>
        </Style.Triggers>
    </style>

    <style targettype="PasswordBox" basedon="{StaticResource {x:Type PasswordBox}}">
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="Validation.HasError" Value="True" />
                    <Condition Property="IsVisible" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ValidationErrorTemplate}"/>
            </MultiTrigger>
        </Style.Triggers>
    </style>
</resourcedictionary>

Или сделайте еще один шаг вперед и избегайте повторения триггеракомбинируя стили:

<resourcedictionary ...="">
    <style x:key="ErrorControlStyle" targettype="Control">
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="Validation.HasError" Value="True" />
                    <Condition Property="IsVisible" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ValidationErrorTemplate}"/>
            </MultiTrigger>
        </Style.Triggers>
    </style>

    <style targettype="PasswordBox" basedon="{extensions:MultiStyle . ErrorControlStyle}">
    <Style TargetType="TextBox" BasedOn="{extensions:MultiStyle . ErrorControlStyle}"/>
</ResourceDictionary>
</code></pre><p>но я'буду держаться подальше от этого подхода, так как он сломает дизайнера.</p><p>В приведенных выше примерах я использовал шаблон с именем<code>ValidationErrorTemplate</code> от<a href="https://github.com/MahApps/MahApps.Metro/blob/develop/src/MahApps.Metro/MahApps.Metro/Styles/ValidationErrorTemplate.xaml">MahApps.Metro</a></p><p><a href="/imgs/xZ2MU.png"><img src="/imgs/xZ2MU.png"></img></a></p><p>Кроме того, нене забудьте также использовать<code>AdornerDecorator</code> внутри<code>TabItem</code> исправить, как описано @ Abyte0, чтобы сохранить проверки при переключении вкладок.</p></style></resourcedictionary>
5

Ошибки проверки WPF исчезают внутри TabControl при переключении элементов TabItem.

<tabcontrol>

  <tabitem>
    <adornerdecorator>
      <stackpanel>
        ...
      </stackpanel>
    </adornerdecorator>
  </tabitem>

  <tabitem>
    <adornerdecorator>
      <stackpanel>
        ...
      </stackpanel>
    </adornerdecorator>
  </tabitem>

  <tabitem>
    <adornerdecorator>
      <stackpanel>
        ...
      </stackpanel>
    </adornerdecorator>
  </tabitem>

</tabcontrol>
Это только часть решения. Он используется для сохранения корректности при переключении между вкладками. Это победилоt работать на вкладках, которые изначально не выбраны. Это может работать, если контекст данных устанавливается на каждомLoaded событие внутри элементов вкладки, событие, которое, кстати, будет срабатывать при каждом переключении вкладок. MoonStom
Поскольку решение не слишком большое, не могли бы вы вставить его? Вы можете использоватьредактировать" кнопка ссылки под вашим ответом, чтобы обновить его. Кроме того, это предотвратит бесполезность вашего ответа, если ссылка в конечном счете прекратится. ForceMagic
20

(Я использую AdornerDecorator, как и в предыдущей программе, в которой стиль ошибок не обновлялся при смене вкладок.

Предположительно этот действительно важный совет исходит изБлог Карла Шифлетапо крайней мере онs обращаясь к той же теме:Ошибки проверки WPF исчезают внутри TabControl при переключении элементов TabItem.

Учитывая это, ваша проблема может быть просто связана, т.е. приведенный выше совет / код гарантирует наличие выделенногоAdornerLayer теперь для каждого элемента вкладки, поскольку слой переключателя родительского элемента отбрасывается при переключении вкладок. Этот выделенный рекламный слой все еще требует особого подхода, см., Например, вопросWPF ErrorTemplate виден, когда не в фокусе? который в основном имеет дело с вашей проблемой с ног на голову. Следовательно, яЯ предлагаю вам объединить и расширить изложенное решение для последнего с вашим стилем и попробовать следующее (хотя непроверенный код на данный момент):

<style x:key="ErrorTemplate" targettype="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">...</Trigger>
        <Trigger Property="IsVisible" Value="false">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        </Trigger>
        <Trigger Property="IsVisible" Value="true">
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>...</Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</style>

Смотрите мой комментарий относительно вашего обновленияСтиль ошибки переключателя тоже, который пытается аналогичным образом ответить на ваш вероятный связанный вопрос; ты на самом деле попробовал мое предложение там?

УвидетьОбзор украшений для получения более подробной информации об архитектуре Adorner.

@dkl 5 лет спустя, и у меня та же проблема. В свое время я использовал ваши идеи. Спасибо! Peter M
Это сработало для меня, чтобы включить проверку после переключения TabItems. Решение на блоге Карла Шиффлетса невозможно, потому что я неУ него есть фиксированное количество TabItems, но динамически добавляем TabItems в TabControl. Похоже, что в этой ситуации необходим триггер для IsVisible == true для повторной установки ErrorTemplate. Спасибо за этот совет! Slauma
Отличное решение. Мне это нравится намного лучше, чем определение AdornerDecorater во всех моих элементах вкладок. Michael Norgren
Вы можете сделать это проще с MultiTrigger: ... dkl
Еще раз спасибо Штеффен. Я видел комментарий, который вы оставили по моему другому вопросу, но я думаю, что к тому времени, когда я добрался до этой проблемы, я забыл об этом. Peter M

Похожие вопросы