WPF TextBox自定义错误检查

事情真的很曲折.

最开始需要画出波浪线. 在考虑过spellcheck不适合之后, 决定自己做一个custom control, 直接继承自TextBox.

修改它的模板, 在里面增加一个listbox, 然后创建一个listbox的style,让其ListBox的ItemPanel为空的Grid从而消除它的边框; 修改ItemContainerStyle使之里面只放一个Path,或者直接修改ItemTemplate使其为一个Path. Path的Data用TemplateBinding绑定到控件里的一个ErrorList中, 用转换类实现从数据转换为Geometry.


画线还没完. 当文本框中的内容很多, 鼠标拖动的时候显示的文本就会变化, 那红线肯定也要相应的变话.

由于计算红线位置的函数是异步的,  一开始是用TextChanged做计算错误位置,然后用SelectionChanged做红线偏移,结果就是SelectionChanged先记录下红线的位置,准备做偏移,同时或者之前或者之后TextChanged准备计算错误位置, 然后TextChanged会先完成然后保存新的位置, 然后SelectionChanged做完偏移又保存一遍,结果TextChanged就白做了... UI元素中加锁肯定不现实,只好改变思路:

因为View和ViewModel完全分离,所以没法直接绑定事件.不过可以利用Interactivity来绑定,把元素自己当做参数传进去.

<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
                    <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding  ElementName=myErrorTextBox}"  />
</i:EventTrigger>
</i:Interaction.Triggers>

在selectionChangedCommand里做错误检查,来更新ErrorList. 这时候只要在TextBox的ErrorList属性的PropertyChangedCallback里加上偏移位置修正就可以了.要注意的是这里不是new 一个ErrorList,而是更改ErrorList里面每个错误的偏移, 因为如果用new就会把原来的数据绑定属性毁了,以后就没法产生更新了.


事情就是这么简单,但是之前试了很多歪路都不得正解,下面列出其中一些:

尝试过使用new出来的ErrorList重新赋给ErrorTextBox, 结果就是错误没法更新了.

尝试过在ErrorTextBox里写一个static的方法,传入一个ErrorTextBox然后修正其错误位置,但是这个方法的根本问题是错误检查是异步的,不论在哪里调用这个static 方法,它的参数都是没有更新位置的ErrorList,然后异步的错误检查更新ErrorList之后,这个没有更新位置的ErrorList会覆盖之,导致线程安全问题.

尝试过把上面的static方法改成非静态,然后在ErrorList更新之后调用这个ErrorTextBox的位置修正方法,但是和上面一样. 跟进去发现ErrorList更新之后虽然ErrorTextBox在修正的时候会把修正位置改入ErrorList,但是红线并不会发生改变并且下一次这个修正位置就丢失了. 猜测是数据绑定的机制造成的原因, 把Mode改成OneWay也没有用.

总之现在看起来效果还不错. 就这样吧.


代码如下:


ErrorTextBox.xaml

    <!--Control colors.-->
    <Color x:Key="WindowColor">#FFE8EDF9</Color>
    <Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
    <Color x:Key="ContentAreaColorDark">#FF7381F9</Color>

    <Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
    <Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
    <Color x:Key="DisabledForegroundColor">#FF888888</Color>

    <Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
    <Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>

    <Color x:Key="ControlLightColor">White</Color>
    <Color x:Key="ControlMediumColor">#FF7381F9</Color>
    <Color x:Key="ControlDarkColor">#FF211AA9</Color>

    <Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
    <Color x:Key="ControlPressedColor">#FF211AA9</Color>


    <Color x:Key="GlyphColor">#FF444444</Color>
    <Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>

    <!--Border colors-->
    <Color x:Key="BorderLightColor">#FFCCCCCC</Color>
    <Color x:Key="BorderMediumColor">#FF888888</Color>
    <Color x:Key="BorderDarkColor">#FF444444</Color>

    <Color x:Key="PressedBorderLightColor">#FF888888</Color>
    <Color x:Key="PressedBorderDarkColor">#FF444444</Color>

    <Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
    <Color x:Key="DisabledBorderDarkColor">#FF888888</Color>

    <Color x:Key="DefaultBorderBrushDarkColor">Black</Color>

    <!--Control-specific resources.-->
    <Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
    <Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
    <Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>

    <Color x:Key="NavButtonFrameColor">#FF3843C4</Color>

    <LinearGradientBrush x:Key="MenuPopupBrush"
                     EndPo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值