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

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

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

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

КакВременное решение: я могу обновить визуальное состояние в событии 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 в codebehind

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);
        }
    }
...