c# - 为 winrt 文本框禁用 "double tap space for period"

标签 c# xaml windows-store-apps winrt-xaml

Windows 8 具有文本编辑控件的功能,可在用户双击空格键后自动插入一个句点。

这可以通过“PC 设置/PC 和设备/键入/双击空格键后添加句点”设置在系统级别打开或关闭。 (此设置似乎并不总是存在 - 在我的 Surface 上存在,但在我的桌面上却不存在;我怀疑它仅在类似平板电脑的设备上可用...)

我需要能够为我正在编写的应用程序中的某个 TextBox 元素禁用此功能。

代替明显的“DisableAutoInsertPeriodsOnSpaceDoubleTap”属性,我尝试了几件事:

1) 拦截空格击键,自己插入空格并将事件标记为已处理,这样它就不会冒泡了:

private void textbox_OnKeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == VirtualKey.Space)
    {
        this.textbox.SelectedText = " ";
        this.textbox.SelectionStart++;
        this.textbox.SelectionLength = 0;
        e.Handled = true;
    }
}

这根本不会影响底层控件的行为,但是如果我用另一个字符替换空格,例如"*",则行为抑制。

如果我尝试插入“*”然后用“”覆盖它,行为返回!

好吧,看来我无法使用该选项。

下一个想法:

2) 处理 TextChanged 事件并用空格覆盖任何自动插入的句点。

乍一看,在双击空格后,句点被插入到 SelectionStart 的左侧两个字符,所以像这样工作:

private void textbox_OnKeyDown(object sender, KeyRoutedEventArgs e)
{
    this.spacePressed = e.Key == VirtualKey.Space;
}

private void textbox_TextChanged(object sender, Windows.UI.Xaml.Controls.TextChangedEventArgs e)
{
    var text = this.textbox.Text;
    var selectionStart = this.textbox.SelectionStart;
    if (this.spacePressed && this.textbox.SelectionLength == 0 && 
        selectionStart > 2 && text[selectionStart - 2] == '.')
    {
        // Move back two characters and overwrite the character there
        this.textbox.SelectionStart -= 2;
        this.textbox.SelectionLength = 1;
        this.textbox.SelectedText = " ";

        // Reposition the cursor back to where it was
        this.textbox.SelectionStart = selectionStart;
        this.textbox.SelectionLength = 0;
    }
}

大获成功!...但只有当文本位于文本框的第一行时...

奇怪的是插入句点后光标位置并不总是一致的。它可以是从光标处到前面 2 个字符的任何位置。这种方法的另一个问题是,有时(我认为当光标位于句点的位置时)用空格替换句点会导致系统锁定,底层控件用句号替换空格,我的代码用空格替换它,来回无限循环。

这个问题的最佳结果是我可以在某处设置一个简单的属性,我浪费了一个小时来解决这个问题。有人吗?

最佳答案

第一次尝试的变体起作用了——用“空格替代”替换空格,例如一个不间断的空间,足以绕过句点插入:

private void textbox_OnKeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == VirtualKey.Space)
    {
        // Spaces are always output as non-breaking spaces
        this.textbox.SelectedText = "\u00A0";
        this.textbox.SelectionStart++;
        this.textbox.SelectionLength = 0;
        e.Handled = true;
    }
}

然后我在返回源代码的绑定(bind)之上添加了一个转换器,确保在返回的路上将不间断空格替换为正常空格:

public class SpaceReplaceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var text = value as string;
        return text != null ? text.Replace(' ', '\u00A0') : value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        var text = value as string;
        return text != null ? text.Replace('\u00A0', ' ') : value;
    }
}

这样使用:

<TextBox Text="{Binding Text, Mode=TwoWay, Converter={StaticResource SpaceReplaceConverter}}" />

希望对其他人有帮助。

关于c# - 为 winrt 文本框禁用 "double tap space for period",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23978823/

相关文章:

c# - 如何从 MVVM 中的 ViewModel 选择数据网格中的一行?

wpf - 如何在没有 AttachedProperty 或 DependencyProperty 的情况下使用 IDataErrorInfo 验证密码框?

.net - Windows 应用商店应用中的转换命名空间在哪里

c# - 侧面加载的 Windows 8 应用程序 - 代理 Windows 运行时组件与 WCF 服务。

c# - Asp .Net 更新面板未更新

c# - 如何从 KeyValuePair 列表中进行选择?

javascript - "ISO-8859-1"JavaScript 中的编码

c# - 调用异步方法和 Task.Run 异步方法之间的区别

javascript - Windows 8 商店应用程序 : how to have the app live tile change constantly of colour (and text)?

C#远程web请求证书报错