在CustomControl上触发事件两次

时间:2018-02-21 15:27:38

标签: c# wpf xaml

问题是KeyDown事件被触发两次,第一次来自CustomTextBox内名为textSource的{​​{1}};第二个,来自名为Style的{​​{1}}中的控制。

linked问题提供了一个解决方案,您可以在其中过滤EventHandler MainWindow来源"CTbox"工作正常:

OnKeyDown

基本上我想知道是否有更好的解决方案,如果有人能解释为什么会发生这种情况以及如何避免它。

该样式意味着在e.Source != "textSource"中创建提示文字或WaterMark,而无需转发if (e.Source is CustomTextBox sourceTextBox && sourceTextBox.Name.Equals("textSource")) { return; }

提前致谢。

按照代码创建此行为的最小,完整和可验证的示例

CustomTextBox


Focus events

1 个答案:

答案 0 :(得分:1)

因此,您将获得两次OnKeyDown处理程序的执行,因为您的XAML实际上是在CustomTextBox中构建CustomTextBox。使用routing strategy WPF事件和您的可视化树看起来像这样:

enter image description here

KeyDown事件自然会在两个地方触发(textsource,然后冒泡到CustomTextBox)。旁注,如果你覆盖OnPreviewKeyDown,你应该得到相反的顺序 - CTbox隧道向下到textSource。

要回答你问题的第二部分 - 如何避免这种情况,我想也许你应该重新考虑你的实现。我的问题是:

  1. 您是否应该在控件模板中使用可编辑控件(在本例中为CustomTextBox)作为hinttext overlay?由于hinttext只能是可读的,所以也许TextBlock就足够了。
  2. 您是否应该覆盖自定义文本框的ControlTemplate以获取此HintText功能?也许更好的方法是创建一个提供此功能的UserControl。即网格包含您的自定义文本框和覆盖它的文本块。这将阻止您使用嵌套的CustomTextBox的可视树。
  3. 如果您需要ControlTemplate以便重复使用它,为什么不将它作为CustomTextBox的默认控件模板?如果您的“Tag”属性未绑定,则hinttext自然不会显示。这样你就不会有嵌套的CustomTextBoxes导致OnKeyDown的重复执行!
  4. 为什么你甚至需要一个CustomTextBox?您是否有其他覆盖代码和行为,您没有显示需要这个?我猜这是因为你展示了一个最小的样本而且还有更多 - 但只是想我会问:)
  5. 编辑评论 鉴于您的澄清/问题,我会通过自定义控件解决这个问题。我知道你拥有的是技术上的自定义控件,但我在谈论的是themes \ generic.xaml文件带来的那种:)。如果您不熟悉,我建议创建一个新的VS项目并使其成为“WPF自定义控件库”模板。然后,您应该能够添加模板“自定义控件(WPF)”的新类。您将看到VS为您生成了themes \ generic.xaml文件 - 您可以在此处为CustomTextBox保存controltemplate。我会get the default control template一个TextBox,并添加一个未被命中测试的TextBlock可见(因此用户可以点击进入你的可编辑区域)并在其上为HintText设置一个TemplateBinding。然后你就可以在任何地方重复使用这个自定义控件(因为它是在一个单独的dll中编译的......你也可以选择将它保存在你当前的项目中),获得你没有覆盖的文本框的默认行为,并且不会嵌套CustomTextBox。