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

.NET MAUI Editor控件文本选择检测与操作功能实现咨询

.NET MAUI Editor文本选择检测与内容获取方案

针对.NET MAUI构建文字处理器时的文本选择需求,无需使用已过时的旧版渲染器,官方推荐用Handlers替代实现跨平台的文本选择监听与内容提取,以下是具体实现方案:

1. 自定义可选择Editor控件

先创建带选择属性的自定义Editor,方便后续绑定和获取选择信息:

using Microsoft.Maui.Controls;

namespace YourAppNamespace;

public class SelectableEditor : Editor
{
    public static readonly BindableProperty SelectedTextProperty =
        BindableProperty.Create(nameof(SelectedText), typeof(string), typeof(SelectableEditor), string.Empty);

    public static readonly BindableProperty SelectionStartProperty =
        BindableProperty.Create(nameof(SelectionStart), typeof(int), typeof(SelectableEditor), 0);

    public static readonly BindableProperty SelectionLengthProperty =
        BindableProperty.Create(nameof(SelectionLength), typeof(int), typeof(SelectableEditor), 0);

    public string SelectedText
    {
        get => (string)GetValue(SelectedTextProperty);
        set => SetValue(SelectedTextProperty, value);
    }

    public int SelectionStart
    {
        get => (int)GetValue(SelectionStartProperty);
        set => SetValue(SelectionStartProperty, value);
    }

    public int SelectionLength
    {
        get => (int)GetValue(SelectionLengthProperty);
        set => SetValue(SelectionLengthProperty, value);
    }
}

2. 各平台Handler实现

Windows平台(核心目标平台)

Windows下Editor映射为TextBox,监听SelectionChanged事件同步选择信息:

using Microsoft.Maui.Platform;
using Microsoft.UI.Xaml.Controls;

namespace YourAppNamespace.Platforms.Windows;

public static class SelectableEditorHandlerExtensions
{
    public static void ConfigureSelectableEditor(this IMauiHandlersCollection handlers)
    {
        handlers.AddHandler<SelectableEditor, SelectableEditorHandler>();
    }
}

public class SelectableEditorHandler : EditorHandler
{
    protected override void ConnectHandler(TextBox platformView)
    {
        base.ConnectHandler(platformView);
        platformView.SelectionChanged += OnSelectionChanged;
    }

    protected override void DisconnectHandler(TextBox platformView)
    {
        platformView.SelectionChanged -= OnSelectionChanged;
        base.DisconnectHandler(platformView);
    }

    private void OnSelectionChanged(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
    {
        if (sender is TextBox textBox && VirtualView is SelectableEditor editor)
        {
            editor.SelectedText = textBox.SelectedText;
            editor.SelectionStart = textBox.SelectionStart;
            editor.SelectionLength = textBox.SelectionLength;
        }
    }
}

Android平台

Android下Editor映射为EditText,通过OnSelectionChangeListener监听选择变化:

using Android.Widget;
using Microsoft.Maui.Platform;

namespace YourAppNamespace.Platforms.Android;

public static class SelectableEditorHandlerExtensions
{
    public static void ConfigureSelectableEditor(this IMauiHandlersCollection handlers)
    {
        handlers.AddHandler<SelectableEditor, SelectableEditorHandler>();
    }
}

public class SelectableEditorHandler : EditorHandler
{
    private TextView.IOnSelectionChangeListener _selectionListener;

    protected override void ConnectHandler(EditText platformView)
    {
        base.ConnectHandler(platformView);
        _selectionListener = new SelectionChangeListener(VirtualView as SelectableEditor);
        platformView.SetOnSelectionChangeListener(_selectionListener);
    }

    protected override void DisconnectHandler(EditText platformView)
    {
        platformView.SetOnSelectionChangeListener(null);
        _selectionListener.Dispose();
        base.DisconnectHandler(platformView);
    }

    private class SelectionChangeListener : Java.Lang.Object, TextView.IOnSelectionChangeListener
    {
        private readonly SelectableEditor _editor;

        public SelectionChangeListener(SelectableEditor editor)
        {
            _editor = editor;
        }

        public void OnSelectionChanged(TextView textView, int start, int end)
        {
            _editor.SelectedText = textView.Text.Substring(start, end - start);
            _editor.SelectionStart = start;
            _editor.SelectionLength = end - start;
        }
    }
}

iOS平台

iOS下Editor映射为UITextView,通过自定义UITextViewDelegate监听选择变化:

using Foundation;
using Microsoft.Maui.Platform;
using UIKit;

namespace YourAppNamespace.Platforms.iOS;

public static class SelectableEditorHandlerExtensions
{
    public static void ConfigureSelectableEditor(this IMauiHandlersCollection handlers)
    {
        handlers.AddHandler<SelectableEditor, SelectableEditorHandler>();
    }
}

public class SelectableEditorHandler : EditorHandler
{
    private CustomTextViewDelegate _customDelegate;

    protected override void ConnectHandler(UITextView platformView)
    {
        base.ConnectHandler(platformView);
        _customDelegate = new CustomTextViewDelegate(VirtualView as SelectableEditor);
        platformView.Delegate = _customDelegate;
    }

    protected override void DisconnectHandler(UITextView platformView)
    {
        platformView.Delegate = null;
        _customDelegate.Dispose();
        base.DisconnectHandler(platformView);
    }

    private class CustomTextViewDelegate : UITextViewDelegate
    {
        private readonly SelectableEditor _editor;

        public CustomTextViewDelegate(SelectableEditor editor)
        {
            _editor = editor;
        }

        public override void SelectionChanged(UITextView textView)
        {
            base.SelectionChanged(textView);
            var selectedRange = textView.SelectedRange;
            _editor.SelectedText = textView.Text.Substring((int)selectedRange.Location, (int)selectedRange.Length);
            _editor.SelectionStart = (int)selectedRange.Location;
            _editor.SelectionLength = (int)selectedRange.Length;
        }
    }
}

3. 注册Handler并使用

在MauiProgram.cs中注册各平台Handler:

builder.ConfigureMauiHandlers(handlers =>
{
#if WINDOWS
    handlers.ConfigureSelectableEditor();
#elif ANDROID
    handlers.ConfigureSelectableEditor();
#elif IOS
    handlers.ConfigureSelectableEditor();
#endif
});

在XAML中使用自定义控件并实现功能:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:YourAppNamespace"
             x:Class="YourAppNamespace.MainPage">

    <VerticalStackLayout Padding="20">
        <local:SelectableEditor x:Name="MyEditor" HeightRequest="200" Placeholder="输入并选中文本..." />
        <Label Text="选中的文本:" Margin="0,10,0,0" />
        <Label Text="{Binding SelectedText, Source={x:Reference MyEditor}}" />
        <Button Text="复制到剪贴板" Clicked="CopySelected_Clicked" Margin="0,10,0,0" />
        <Button Text="标记选中文本为粗体" Clicked="BoldSelected_Clicked" />
    </VerticalStackLayout>
</ContentPage>

后台代码实现剪贴板和格式设置逻辑:

private async void CopySelected_Clicked(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(MyEditor.SelectedText))
    {
        await Clipboard.SetTextAsync(MyEditor.SelectedText);
    }
}

private void BoldSelected_Clicked(object sender, EventArgs e)
{
    if (MyEditor.SelectionLength <= 0) return;

    // 示例:给选中文本前后添加Markdown粗体标记
    var fullText = MyEditor.Text;
    var newText = fullText.Insert(MyEditor.SelectionStart + MyEditor.SelectionLength, "**")
                          .Insert(MyEditor.SelectionStart, "**");
    MyEditor.Text = newText;

    // 恢复选中范围(可选)
    MyEditor.SelectionStart = MyEditor.SelectionStart;
    MyEditor.SelectionLength = MyEditor.SelectedText.Length + 4;
}

注意事项

  • 该方案基于.NET MAUI官方推荐的Handlers模式,完全兼容最新版本,替代了已过时的渲染器方案。
  • 跨平台兼容:Windows/Android/iOS均已实现,macOS可参考iOS逻辑适配。
  • 若需实现真正的富文本格式(如字体颜色、字号),可基于原生控件扩展,Editor控件仅适用于纯文本或标记类文本处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:27:21