代码之家  ›  专栏  ›  技术社区  ›  Phil Sandler

wpf控制行为与调用的一般问题

  •  2
  • Phil Sandler  · 技术社区  · 14 年前

    我一直推迟活动,因为我现在的名声是“1337”。:)

    这是一个“为什么”而不是“如何”的问题。默认情况下,wpf在打开窗口时似乎不会将焦点设置为窗口中的第一个控件。此外,当文本框获得焦点时,默认情况下它没有选中它的现有文本。所以基本上,当我打开一个窗口时,我想把焦点放在窗口的第一个控件上,如果这个控件是一个文本框,我想选择它的现有文本(如果有的话)。

    我在网上找到了一些实现这些行为的技巧,并将它们结合起来。下面的代码,我放在我的窗口的构造函数中,是我想到的:

    Loaded += (sender, e) =>
              {
                  MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
                  var textBox = FocusManager.GetFocusedElement(this) as TextBox;
                  if (textBox != null)
                  {
                      Action select = textBox.SelectAll;
                      //for some reason this doesn't work without using invoke.
                      Dispatcher.Invoke(DispatcherPriority.Loaded, select);
                  }
              };
    

    所以,我的问题。为什么在不使用dispatcher.invoke的情况下上面的操作不起作用?窗口(或文本框)的行为中是否有内置的内容导致加载后取消选定的文本?

    可能相关,也可能不相关--另一个我必须使用Dispatcher.Invoke来控制窗体行为的示例:

    WPF Focus In Tab Control Content When New Tab is Created

    2 回复  |  直到 14 年前
        1
  •  1
  •   Dan Puzey    14 年前

    所有wpf控件都具有线程关联性。这个 Dispatcher 管理在其上创建每个控件的线程(通常这是应用程序中每个控件的单个线程,但不一定)。工作在此线程上排队并按优先级顺序执行。

    任何ui操作代码都必须在创建控件的同一线程上执行。 调度员 线程-因此任何方法都必须调用回该线程,然后才能执行任何会影响ui的操作(例如在 TextBox )

    也就是说,我的理解是 Loaded 默认情况下,eventhandler会在dispatcher线程上触发,所以我不完全确定您在特定示例中看到这种行为的原因!

        2
  •  1
  •   J Rothe    14 年前

    首先,我要提到的是,在.net 4.0中使用dispatcher调用(它可能已经在框架更新中被修复)来实现这一点是没有问题的——然而,前面的海报所提到的是准确的,自从winforms(.doActions()和.invoke()出现以来,它就一直是一个难题。但是,在3.5中,如果在lambda中使用在codebhind中定义的方法作为目标调用,则上述方法在w/out dispatcher中确实有效:

      Loaded += (sender, e) =>
      {
       this.SelectText();
      };  
    
      void SelectText()
      {
       MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
       var textBox = FocusManager.GetFocusedElement(this) as TextBox;
    
       if (textBox != null)
       {
        textBox.SelectAll();
       }
      }
    

    至于原因,我真的不能告诉你细节,但我遇到了类似的问题,使用lambdas在演示者上路由事件。我想说的是使用编译表达式的引用或上下文来做一些事情-在这种情况下,它需要引用包含对象,以便知道如何委托操作(选择右边线程上的文本框文本)。我也相信gc偶尔会清理资源,这样延迟的执行就会变得一团糟(在f……中可以看到它……相信这也是我在c中出现问题的原因)。