0

基本上在我的应用程序中,我有一个RichEditBox需要将其数据保存在TextChanged事件中并从保存的设置OnLoaded事件中加载文本,经过数周的实验,我能够在一个最小的应用程序中重现该问题供你们测试。

目标:最终,无论我使用深色或浅色主题将 RTF 文本保存在此丰富的编辑框中,无论何时以任何主题再次加载它都应在深色和浅色主题中显示正确的文本颜色。并且在运行应用程序期间,如果用户更改其设备的主题,文本颜色也应按预期更改。我不确定如何在此处保存 rtf 文本,它可能会忽略文本颜色?

在这里重现错误https ://github.com/touseefbsb/RichEditBoxColorBug

  1. 确保您的设备主题为“黑暗”。
  2. 运行应用程序并将一些文本添加到 RichEditBox 中(顶部的文本块和按钮只是为了确保应用程序在页面加载时不会自动聚焦在richeditbox 上)。

图 1

图 2

  1. 单击屏幕上的其他位置以从richeditbox 中释放焦点,然后关闭应用程序。
  2. 再次运行应用程序,您会注意到之前输入的文本已经按预期出现,现在关闭应用程序。

图 3

  1. 将您设备的主题设置为“Light”并再次运行应用程序,现在您会注意到richeditbox 似乎是空的。

图 4

  1. 但实际上它不是空的,问题是文本颜色是白色的,就像richeditbox的颜色一样,而文本颜色在浅色主题中应该是黑色的。这可以通过用光标选择文本并注意突出显示的文本来证明。

图 5

笔记

每次您更改某些内容并尝试再次测试整个流程时,只需确保更改LoadedTextChanged事件中的 字符串,以确保保存并稍后加载全新的RTF值,加载和文本更改事件中的键必须始终匹配,并且每次您想从第 1 步开始时都应更改。

图 6

代码

Xaml

 <StackPanel>
    <TextBlock>abc</TextBlock>
    <Button>abc</Button>
    <RichEditBox
        x:Name="REB"
        Height="60"
        AcceptsReturn="True"
        BorderThickness="0"
        Loaded="REB_Loaded"
        PlaceholderText="placeholder."
        TextChanged="REB_TextChanged"
        TextWrapping="Wrap" />
</StackPanel>

代码背后

private void REB_Loaded(object sender, RoutedEventArgs e)
    {
        var localSettings = ApplicationData.Current.LocalSettings;
        var localValue = localSettings.Values["ts5"] as string; // Change the key value on every new test
        var text = string.IsNullOrEmpty(localValue) ? string.Empty : localValue;
        REB.Document.SetText(TextSetOptions.FormatRtf, text);
    }

    private void REB_TextChanged(object sender, RoutedEventArgs e)
    {
        var localSettings = ApplicationData.Current.LocalSettings;
        REB.Document.GetText(TextGetOptions.FormatRtf, out var tmpNar);
        if (!string.IsNullOrEmpty(tmpNar) && !string.IsNullOrWhiteSpace(tmpNar))
        {
            localSettings.Values["ts5"] = tmpNar; // Change the key value on every new test
        }
    }

杂项信息

Windows 10 设备版本:1903

项目目标和最小 sdk 版本:1903

4

1 回答 1

1

我在尝试将 RTF 从RichEditBox.

介绍

只要我们假设您不允许更改字体颜色,这并不难。如果您允许通过文档更改字体颜色,这两个建议的选项也可以工作,但这会带来很多工作和权衡(即,在深色显示时是否反转浅色主题中选择的颜色?,某些颜色用黑色看起来更好背景,其他有白色等)

1.改变ITextDocument

这个选项非常简单并且效果很好。在下面RichEditBox有一个ITextDocument包含实际文本(通过 访问RichEditBox.Document)。设置完本文档的文本后,您还可以设置字体颜色(甚至可以通过这种方式更改文本某些部分的字体颜色):

REB_Loaded

private void REB_Loaded(object sender, RoutedEventArgs e)
{
    var localSettings = ApplicationData.Current.LocalSettings;
    var localValue = localSettings.Values["ts4"] as string;
    var text = string.IsNullOrEmpty(localValue) ? string.Empty : localValue;
    REB.Document.SetText(TextSetOptions.FormatRtf, text);

    // Select all text currently in the RichtEditBox 
    // and make it white or black depending on the currently requested theme
    REB.Document.GetRange(0, text.Length).CharacterFormat.ForegroundColor =
        Window.Current.Content is FrameworkElement fe
            ? fe.ActualTheme == ElementTheme.Dark
                ? Windows.UI.Colors.White
                : Windows.UI.Colors.Black
            : Windows.UI.Colors.Black; // Assume light theme if actual theme cannot be determined
}

我已经对此进行了测试,这似乎也有效。

2.更改RTF

一种更底层的方法是在您从 加载原始 RTF 之后LocalSettings以及在设置RichEditBox. 如果您检查原始 RTF,您会看到如下内容:

{\rtf1\fbidis\ansi\ansicpg1252\deff0\nouicompat\deflang2057{\fonttbl{\f0\fnil\fcharset0 Segoe UI;}{\f1\fnil Segoe UI;}}
{\colortbl ;\red255\green255\blue255;}
{\*\generator Riched20 10.0.19041}\viewkind4\uc1 
\pard\tx720\cf1\f0\fs21\lang1033 test text\f1\par}

这里要注意的是第二行: {\colortbl ...},这部分定义了字体颜色。如果您现在只是将 255 更改为 0,则您将字体从白色更改为黑色。我已经编写了两种扩展方法,并且您的代码中的快速测试似乎有效:

扩展类

public static class Extensions
{
    public static string ConvertWhiteTextToBlack(this string s)
        => s.Replace("\\red255\\green255\\blue255", "\\red0\\green0\\blue0");

    public static string ConvertBlackTextToWhite(this string s)
        => s.Replace("\\red0\\green0\\blue0", "\\red255\\green255\\blue255");
}

REB_Loaded

private void REB_Loaded(object sender, RoutedEventArgs e)
{
    var localSettings = ApplicationData.Current.LocalSettings;
    var localValue = localSettings.Values["ts4"] as string;
    var text = string.IsNullOrEmpty(localValue) ? string.Empty : localValue;

    System.Diagnostics.Debug.WriteLine("[REB_Loaded (start)]" + text);
    // Make black text white if dark theme is requested
    text = Window.Current.Content is FrameworkElement fe
        ? fe.ActualTheme == ElementTheme.Light
            ? text.ConvertWhiteTextToBlack()
            : text.ConvertBlackTextToWhite()
        : text.ConvertWhiteTextToBlack(); // Assume light theme if actual theme cannot be determined
    System.Diagnostics.Debug.WriteLine("[REB_Loaded (end)]" + text);

    REB.Document.SetText(TextSetOptions.FormatRtf, text);
}

PS 我希望这些解决方案也适用于您的 MVCE 之外和您的主应用程序。如果没有回复,我会尽力帮助你。
PPS 您无需更改整个 PC 主题即可将应用程序从暗变为亮。相反,只需将标题中的RequestedTheme属性设置为or 或。PageMainPage.xamlLightDark

于 2021-01-11T22:52:52.447 回答