RichEditBox теряет форматирование цвета при отключении и включении

Я использую RichEditBox в приложении UWP, и мне нужно включать и отключать его в программном обеспечении для выполнения некоторых задач. Проблема, с которой я сталкиваюсь, заключается в том, что когда я отключаю, а затем снова включаю его, любое цветовое форматирование теряется. Я создал здесь простой пример, чтобы опробовать проблему. Вы можете ввести текст, окрасить его в красный цвет, а затем отключить и снова включить. Цвет становится черным.

XAML

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <Button Content="Disable" Click="OnDisable"/>
        <Button Content="Enable" Click="OnEnable"/>
        <Button Content="Red" Click="OnRed"/>
    </StackPanel>
    <RichEditBox Name="RichEditor" Width="500" Height="200"/>
</StackPanel>

C#

private void OnDisable(object sender, RoutedEventArgs e)
{
    RichEditor.IsEnabled = false;
}

private void OnEnable(object sender, RoutedEventArgs e)
{
    RichEditor.IsEnabled = true;
}

private void OnRed(object sender, RoutedEventArgs e)
{
     RichEditor.Document.Selection.CharacterFormat.ForegroundColor = Colors.Red;
}

Это похоже на ошибку в компоненте RichEditBox, и мне интересно, есть ли у кого-нибудь обходной путь, позволяющий мне включать и отключать текст без потери цветового форматирования. Ниже приведен пример воспроизведения проблемы.


person ClaudiaWey    schedule 07.10.2018    source источник


Ответы (2)


См. Стиль и шаблон элемента управления в RichEditBox Класс:

Вы можете изменить стиль по умолчанию и ControlTemplate, чтобы придать элементу управления уникальный внешний вид. Стиль по умолчанию, шаблон и ресурсы, которые определяют внешний вид элемента управления, включены в файл generic.xaml. В целях разработки generic.xaml доступен в папке (Program Files) \ Windows Kits \ 10 \ DesignTime \ CommonConfiguration \ Neutral \ UAP ‹Версия SDK> \ Generic из установки Windows Software Development Kit (SDK). Стили и ресурсы из разных версий SDK могут иметь разные значения.

Итак, вы можете найти стиль по умолчанию для элемента управления System.Windows.Controls.RichEditBox, вот целевой стиль по умолчанию в версии 1803:

<!-- Default style for System.Windows.Controls.RichEditBox -->
        <Style TargetType="RichEditBox">
            <Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
            <Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
            <Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
            <Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
            <Setter Property="ContentLinkForegroundColor" Value="{ThemeResource ContentLinkForegroundColor}" />
            <Setter Property="ContentLinkBackgroundColor" Value="{ThemeResource ContentLinkBackgroundColor}" />
            <Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}" />
            <Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}" />
            <Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
            <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
            <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
            <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
            <Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
            <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
            <Setter Property="TextWrapping" Value="Wrap" />
            <Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
            <Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="RichEditBox">
                        <Grid>

                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">

                                    <VisualState x:Name="Disabled">

                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Normal" />

                                    <VisualState x:Name="PointerOver">

                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundPointerOver}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundPointerOver}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Focused">

                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundFocused}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocused}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushFocused}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}" />
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="RequestedTheme">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Light" />
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>

                            </VisualStateManager.VisualStateGroups>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <Border x:Name="BorderElement"
                            Grid.Row="1"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Grid.ColumnSpan="2"
                            Grid.RowSpan="1" />
                            <ContentPresenter x:Name="HeaderContentPresenter"
                            x:DeferLoadStrategy="Lazy"
                            Visibility="Collapsed"
                            Grid.Row="0"
                            Foreground="{ThemeResource TextControlHeaderForeground}"
                            Margin="0,0,0,8"
                            Grid.ColumnSpan="2"
                            Content="{TemplateBinding Header}"
                            ContentTemplate="{TemplateBinding HeaderTemplate}"
                            FontWeight="Normal" />
                            <ScrollViewer x:Name="ContentElement"
                            Grid.Row="1"
                            HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
                            HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                            VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
                            VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
                            IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
                            IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
                            IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
                            Margin="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}"
                            IsTabStop="False"
                            ZoomMode="Disabled"
                            AutomationProperties.AccessibilityView="Raw" />
                            <TextBlock x:Name="PlaceholderTextContentPresenter"
                            Grid.Row="1"
                            Foreground="{ThemeResource TextControlPlaceholderForeground}"
                            Margin="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}"
                            Grid.ColumnSpan="2"
                            Text="{TemplateBinding PlaceholderText}"
                            TextAlignment="{TemplateBinding TextAlignment}"
                            IsHitTestVisible="False" />

                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Из стиля выше вы можете увидеть Disabled VisualState код:

<VisualState x:Name="Disabled">

    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

В этом Disabled VisualState можно найти что Foreground ContentElement будет ThemeResource TextControlForegroundDisabled, когда вы отключите RichEditBox. Поскольку текст Foreground был изменен при отключении RichEditBox, вы теряете цветовой формат.

Вы можете сохранить формат цвета, удалив код изменения ContentElement Foreground как следующий Disabled VisualState:

<VisualState x:Name="Disabled">

    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
        </ObjectAnimationUsingKeyFrames>
        <!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>-->
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}" />
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>
person Breeze Liu - MSFT    schedule 09.10.2018
comment
Это сработало в моем примере кода. Это еще не работает в моем приложении, где цвет возвращается к черному при восстановлении фокуса. Думаю, мне просто нужно выяснить, что еще происходит, но я доволен вашим решением. Большое спасибо!! - person ClaudiaWey; 10.10.2018
comment
Я выясняю, в чем разница в моем примере. Я использую TextToolbar, и это приводит к тому, что цвет возвращается к черному OnFocus. Это ошибка TextToolbar? Есть предложения о том, как это предотвратить? - person ClaudiaWey; 10.10.2018
comment
Исправление, я думаю, это происходит, когда я прикрепляю TextToolbar к RichEditBox. Текст становится черным. Есть предложения о том, как это предотвратить? - person ClaudiaWey; 10.10.2018
comment
@ClaudiaWey Я попытался добавить TextToolbar к RichEditBox, но не смог найти, что он возвращает текст к черному цвету. Вы можете опубликовать новую ветку с подробным кодом и инструкциями, которые помогут мне разобраться в проблеме. - person Breeze Liu - MSFT; 10.10.2018

person    schedule
comment
к сожалению, это не работает. Изменение вступает в силу не сразу. Я мог бы внести это изменение в RichEditor.IsEnabledChanged, но это тоже не сработало бы, потому что цвет применялся только к области текста. У меня может быть черный текст с синим словом и красным словом. Эта информация хранится в формате RTF RichEditBox, но цвет теряется при отключении и повторном включении элемента управления. Единственным обходным решением было сохранить текст в формате RTF до потери фокуса и заново установить его после. Похоже на хакерство, но не могу придумать лучшего способа. Не могли бы вы? - person ClaudiaWey; 07.10.2018