Добавление нового визуального состояния в CommonStates в унаследованных элементах управления

Я наследую DatePicker, чтобы добавить поведение IsReadOnly и InputRequired. сделали соответствующие визуальные состояния для обоих в CommonStates. Причина, по которой я поместил его в CommonStates, заключается в том, что они оба являются взаимоисключающими с состоянием Normal (я проверил TextBox и это та же самая реализация для IsReadOnly).

Проблема, с которой я сталкиваюсь, заключается в том, что даже если я применяю состояние InputRequired в OnApplyTemplate, оно фактически не обновляет внешний вид. Это происходит, однако, после события MouseEnter, что приводит к выводу, что это только начальная конструкция / рендеринг.

Из изучения исходного кода элемента Control видно, что в OnPostApplyTemplate он вызывает внутренний виртуальный метод UpdateVisualState, который переопределяется в DatePicker и который применяет состояние "Normal", что означает, что мое обновление визуального состояния в OnApplyTemplate перезаписывается Control,

В качестве обходного пути я могу обновить визуальное состояние в событии Loaded, а также сделать его отдельной VisualStateGroup и иметь более сложную логику в коде, чтобы определить, применяется ли визуальное состояние (например, inputrequired не следует применять с отключенным / только для чтения), но оба они чувствуют себя немного взломанными.

Итак, мои вопросы: есть ли правильный способ для добавления новых визуальных состояний в CommonStates элемента управления таким образом? Или это лучший способ прослушать событие Loaded и обновить визуальное состояние здесь (и есть ли какие-либо ошибки в этом случае)?

Визуальные состояния:

    <VisualStateGroup x:Name="CommonStates">
    <VisualState x:Name="Normal"/>
    <VisualState x:Name="MouseOver">
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="Background" Storyboard.TargetProperty="Fill">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource CommonHoverBackgroundColor}"/>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="Background" Storyboard.TargetProperty="Stroke">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource CommonHoverBorderColor}"/>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="ReadOnly">
        <Storyboard>
            <DoubleAnimation To="1" Duration="0" Storyboard.TargetName="ReadOnlyVisual" Storyboard.TargetProperty="Opacity"/>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="InputRequired">
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="Background" Storyboard.TargetProperty="Fill">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource CommonRequiredBackgroundColor}"/>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="Disabled">
        <Storyboard>
            <DoubleAnimation To="1" Duration="0" Storyboard.TargetName="PART_DisabledVisual" Storyboard.TargetProperty="Opacity"/>
        </Storyboard>
    </VisualState>
</VisualStateGroup>

UpdateVisualState в коде позади

private void UpdateVisualState(bool useTransitions = true)
    {
        // Common states
        if (IsEnabled == false)
        {
            VisualStateManager.GoToState(this, "Disabled", useTransitions);
        }
        else if (IsMouseOver)
        {
            VisualStateManager.GoToState(this, "MouseOver", useTransitions);
        }
        else if (IsReadOnly)
        {
            VisualStateManager.GoToState(this, "ReadOnly", useTransitions);
        }
        if (CheckInputRequired())
        {
            VisualStateManager.GoToState(this, "Required", useTransitions);
        }
        else
        {
            VisualStateManager.GoToState(this, "Normal", useTransitions);
        }

        if (IsKeyboardFocusWithin)
        {
            VisualStateManager.GoToState(this, "Focused", useTransitions);
        }
        else
        {
            VisualStateManager.GoToState(this, "Unfocused", useTransitions);
        }

        // Clearable states
        if (IsReadOnly == false && AllowNull && SelectedDate != null)
        {
            VisualStateManager.GoToState(this, "Clearable", useTransitions);
        }
        else
        {
            VisualStateManager.GoToState(this, "Unclearable", useTransitions);
        }

        // Watermark states
        if (IsKeyboardFocusWithin)
        {
            // When control has keyboard focus, always hide watermark.
            VisualStateManager.GoToState(this, "Unwatermarked", useTransitions);
        }
        else if (string.IsNullOrWhiteSpace(_datePickerTextBox?.Text) == false)
        {
            // If datepicker has any text, hide watermark.
            VisualStateManager.GoToState(this, "Unwatermarked", useTransitions);
        }
        else
        {
            VisualStateManager.GoToState(this, "Watermarked", useTransitions);
        }
    }

0 ответов

Другие вопросы по тегам