You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Avalon Text Editor选中特殊字符时显示异常(\或__)求助

AvalonEdit JSON文本选中特殊字符显示异常修复方案

问题现象

在封装的CustomizedPrettyJSONTextBox中输入"some, text",双击选中逗号时自动显示反斜杠\;选中{或}等字符时显示__,存在怪异的显示异常。

代码背景

为实现多窗口复用,将AvalonEdit封装为CustomizedPrettyJSONTextBox类,把Text设为依赖属性用于ViewModel双向绑定,语法高亮采用官方JSON.xshd规则。

封装类代码

public class CustomizedPrettyJSONTextBox : TextEditor, INotifyPropertyChanged
{
    public CustomizedPrettyJSONTextBox()
    {
        using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("mynamespace.JSONSyntaxColoringRule.xshd"))
        {
            if (stream != null)
            {
                using (XmlReader reader = new XmlTextReader(stream))
                {
                    IHighlightingDefinition highlightingDefinition = HighlightingLoader.Load(reader, HighlightingManager.Instance);
                    ((TextEditor)this).SyntaxHighlighting = highlightingDefinition;
                }
            }
        }
    }

    public static DependencyProperty TextProperty =
    DependencyProperty.Register("Text",
                                typeof(string), typeof(CustomizedPrettyJSONTextBox),
    new PropertyMetadata((obj, args) =>
    {
        CustomizedPrettyJSONTextBox target = (CustomizedPrettyJSONTextBox)obj;
        if (target.Text != (string)args.NewValue)
            target.Text = (string)args.NewValue;
    })
    );

    public string Text
    {
        get { return base.Text; }
        set { base.Text = value; }
    }

    protected override void OnTextChanged(EventArgs e)
    {
        SetCurrentValue(TextProperty, base.Text);
        RaisePropertyChanged(TextProperty.Name);
        base.OnTextChanged(e);
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    public void RaisePropertyChanged(string info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

XAML使用示例

<mynamespace:CustomizedPrettyJSONTextBox x:Name="avalonJSONTextBox" Margin="10" Grid.Row="2"
                                         Style="{StaticResource CustomJSONTextBoxStyle}" >
    <Binding Path="MyViewModelProperty" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
        <Binding.ValidationRules>
            <commonItems:JSONValidator />
        </Binding.ValidationRules>
    </Binding>
</mynamespace:CustomizedPrettyJSONTextBox>

问题根源

  1. 循环触发的属性更新:自定义Text依赖属性的回调中直接赋值target.Text = args.NewValue,而Text的setter又调用base.Text = value,同时OnTextChanged里再用SetCurrentValue更新依赖属性,形成循环触发,导致文本被意外转义或替换。
  2. 冗余的属性变更通知:AvalonEdit的TextEditor本身已内置属性变更通知逻辑,额外实现INotifyPropertyChanged并在OnTextChanged中触发,干扰了原有文本处理流程。

修复方案

方案1:修复依赖属性回调逻辑

修改依赖属性的PropertyChanged回调,使用SetCurrentValue更新基类的TextProperty,避免循环触发:

public static DependencyProperty TextProperty =
DependencyProperty.Register("Text",
                            typeof(string), typeof(CustomizedPrettyJSONTextBox),
new PropertyMetadata((obj, args) =>
{
    CustomizedPrettyJSONTextBox target = (CustomizedPrettyJSONTextBox)obj;
    string newValue = args.NewValue as string;
    if (target.base.Text != newValue)
    {
        target.SetCurrentValue(TextEditor.TextProperty, newValue);
    }
})
);

方案2:简化封装类实现

直接复用基类的TextProperty,移除冗余的自定义Text属性和INotifyPropertyChanged实现:

public class CustomizedPrettyJSONTextBox : TextEditor
{
    public CustomizedPrettyJSONTextBox()
    {
        using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("mynamespace.JSONSyntaxColoringRule.xshd"))
        {
            if (stream != null)
            {
                using (XmlReader reader = XmlReader.Create(stream))
                {
                    IHighlightingDefinition highlightingDefinition = HighlightingLoader.Load(reader, HighlightingManager.Instance);
                    SyntaxHighlighting = highlightingDefinition;
                }
            }
        }
    }

    // 直接使用基类的TextProperty进行绑定,无需额外封装
}

方案3:调整OnTextChanged逻辑

若需保留自定义Text属性,修改OnTextChanged仅在值不同时更新依赖属性:

protected override void OnTextChanged(EventArgs e)
{
    string currentText = base.Text;
    if (currentText != GetValue(TextProperty) as string)
    {
        SetCurrentValue(TextProperty, currentText);
    }
    base.OnTextChanged(e);
}

额外检查

确保嵌入的JSONSyntaxColoringRule.xshd文件与官方版本一致,没有被修改导致特殊字符的高亮规则出现错误(比如错误的转义或替换配置)。

内容的提问来源于stack exchange,提问作者Vignesh G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 03:52:06