none
关于WFP TextBox控件输入中文的问题 RRS feed

  • 问题

  • RT:今天在做一个用户名输入限制的时候在对TextBox控件的Text输入做限制的时候发现再输入中文的标点符号是 TextBox控件的PreviewTextInput事件和TextBoxChanged事件的引发顺序出现问题并且会报出一个错误。这个错误的引发应该是在TextBoxChange事件里面所写函数出现的,就是对TextBox.Text重新赋值时出现的。不知道为什么会这样,请大神帮忙看看。。。。。。。

    未处理 System.InvalidOperationException
      Message=无法关闭撤消单元,因为不存在已打开的单元。
      Source=PresentationFramework
      StackTrace:
           在 MS.Internal.Documents.UndoManager.Close(IParentUndoUnit unit, UndoCloseAction closeAction)
           在 System.Windows.Documents.ImmComposition.CloseCompositionUndoUnit(UndoCloseAction undoCloseAction, ITextPointer compositionEnd)
           在 System.Windows.Documents.ImmComposition.UpdateCompositionText(FrameworkTextComposition composition, Int32 resultLength, Boolean includeResultText, ITextPointer& start, ITextPointer& end)
           在 System.Windows.Documents.ImmComposition.RaiseTextInputStartEvent(FrameworkTextComposition composition, Int32 resultLength, String compositionString)
           在 System.Windows.Documents.ImmComposition.OnWmImeChar(IntPtr wParam, Boolean& handled)
           在 System.Windows.Documents.ImmComposition.ImmCompositionFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
           在 System.Windows.Interop.HwndSource.PublicHooksFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
           在 MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
           在 MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
           在 System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
           在 MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
           在 System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
           在 MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
           在 MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
           在 MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
           在 MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
           在 MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
           在 MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
           在 System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
           在 System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
           在 System.Windows.Application.RunDispatcher(Object ignore)
           在 System.Windows.Application.RunInternal(Window window)
           在 System.Windows.Application.Run(Window window)
           在 System.Windows.Application.Run()
           在 LiveChainCHIS_Client.App.Main() 位置 D:\项目\LiveChainCHIS-Client\LiveChainCHIS-Client\obj\x86\Debug\App.g.cs:行号 0
           在 System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
           在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           在 System.Threading.ThreadHelper.ThreadStart()
      InnerException: 

    补充说明一下 ,这个错误只出现于 数据绑定后的TextBox控件上,也不知道是为什么!

    2012年12月17日 6:06

答案

  • 首先你例子有些问题,

    1)你设置textBox.Text = textBox.Text.Remove(offset, change[0].AddedLength);,会导致TextChanged事件再触发一次。

    2)你说的绑定不会起作用,因为后台你Text=。。。 这样的赋值语句会让绑定自动断掉的。


    Sheldon _Xiao
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年12月18日 8:59
    版主

全部回复

  • 把你这两个事件中的代码贴一下。
    2012年12月17日 6:18
  • 把你这两个事件中的代码贴一下。

    我自己做了一个小的demo 发出来大家看看吧!

    xaml

                    <TextBox Height="88" HorizontalAlignment="Left" Margin="221,38,0,0" TextChanged="textBox1_TextChanged" Name="textBox1"
                             Text="{Binding MyText,UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="303" />

    cs

            this.textBox1.DataContext = new testBase();

        public class testBase : INotifyPropertyChanged
        {

            private string myText;

            public string MyText
            {
                get { return myText; }
                set
                {
                    myText = value;
                    this.RaisePropertyChanged("MyText");
                }
            }

            public void RaisePropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;
        }


            private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
            {
                var textBox = sender as TextBox;
                TextChange[] change = new TextChange[e.Changes.Count];
                e.Changes.CopyTo(change, 0);
                int offset = change[0].Offset;
                bool isvalidation = false;
                if (change[0].AddedLength > 0)
                {
                    isvalidation = !Regex.IsMatch(textBox.Text, @"^\w*$");
                                  textBox.Text = textBox.Text.Remove(offset, change[0].AddedLength);
                                textBox.Select(offset, 0);
                }
            } 

    在TextBox里面输入中文的标点符号 就会报错。输入英文或者英文标点符号没有任务问题。

    这样报出来的错误提示和我在项目中的不太一样,不过都提到了 {"无法关闭撤消单元,因为不存在已打开的单元。"} 这个问题。



    2012年12月17日 7:09
  • 使用你的代码,在我测试中没有任何异常,当然,编辑框里也不会显示任何文字。

    2012年12月17日 7:52
  • 使用你的代码,在我测试中没有任何异常,当然,编辑框里也不会显示任何文字。

    你的TextBox.Text 绑定了吗?

    不过还是谢谢你,我已经找到解决方法了。

    TextBox.Text的UndoLimit属性设置为0就可以了。就不在报错了。

    但是还是不太清楚为什么会出现这个问题。

    2012年12月17日 7:57
  • 绑定了,完全抄的你得代码,而且 UndoLimit 的值是 -1。

    根据你提到的这个属性,我使用了 Ctrl + z 来测试,int offset = change[0].Offset; 会报错,因为 change 的元素为 0,

    然后我按照你提示的将 UndoLimit 设置为 0 ,上述错误消失。

    因此,你得错可能是由你的输入法或你的代码触发了Ctrl+z操作所致。

    2012年12月17日 8:19
  • 绑定了,完全抄的你得代码,而且 UndoLimit 的值是 -1。

    根据你提到的这个属性,我使用了 Ctrl + z 来测试,int offset = change[0].Offset; 会报错,因为 change 的元素为 0,

    然后我按照你提示的将 UndoLimit 设置为 0 ,上述错误消失。

    因此,你得错可能是由你的输入法或你的代码触发了Ctrl+z操作所致。

    你是在中文输入的情况下 输入标点符号吗?如果不是中文状态是不会报错的。UndoLimit默认值 就报错 为0就ok了 但是撤销功能就没有了。哎
    2012年12月17日 8:48
  • 我确定是中文状态下,而且我用的是“微软拼音 — 新体验2010”,别告诉我你用的是什么 Sougo,qq,360云输入法。

    2012年12月17日 9:00
  • 首先你例子有些问题,

    1)你设置textBox.Text = textBox.Text.Remove(offset, change[0].AddedLength);,会导致TextChanged事件再触发一次。

    2)你说的绑定不会起作用,因为后台你Text=。。。 这样的赋值语句会让绑定自动断掉的。


    Sheldon _Xiao
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年12月18日 8:59
    版主