65.9K
CodeProject 正在变化。 阅读更多。
Home

捕获 ContentPresenter 中的内容更改

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2016年5月5日

CPOL

2分钟阅读

viewsIcon

23544

downloadIcon

257

本文介绍了一种捕获DependencyObject上PropertyChanged事件的方法,在本例中用于捕获ContentPresenter上的Content何时更改并设置焦点。

引言

我需要在一个TextBox上设置初始焦点,但有一个问题。当包含TextBoxUserControl出现时,总有一个位于前景的UserControl提供忙碌信息或错误情况。因此,在初始化或加载时设置焦点的常规方法不起作用。更糟糕的是,我将主窗口设计为使用ContentPresenters,其Content用于确定与Content关联的ViewModel所使用的DataTemplate

控件

用于捕获ContentPresenterContent中更改的代码是通过创建一个新的、从ContentPresenter派生的Control来完成的。

 public class ActionableContentPresenter : ContentPresenter
 {
  static ActionableContentPresenter()
  {
   ContentProperty.OverrideMetadata(typeof(ActionableContentPresenter),
    new FrameworkPropertyMetadata(new PropertyChangedCallback(OnContentChanged)));
  }

  private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
   var mcc = d as ActionableContentPresenter;
   mcc?.ContentChanged?.Invoke(mcc, 
         new DependencyPropertyChangedEventArgs(ContentProperty, e.OldValue, e.NewValue));
  }
  public event DependencyPropertyChangedEventHandler ContentChanged;
 }

然后,在主窗口(或UserControl)中,只需要将一个event处理程序关联到此ControlContentChanged event

  public MainWindow()
  {
   InitializeComponent();
   ActionableContentPresenter.ContentChanged += ActionableContentPresenter_ContentChanged;
  }

在本文章的示例中,我只是检查ActionableContentPresenterContent是否为null,如果是,则可以设置焦点。

  private void ActionableContentPresenter_ContentChanged(object sender, 
                             DependencyPropertyChangedEventArgs e)
  {
   var mcc = sender as ActionableContentPresenter;
   if (mcc.Content == null )
   {
    if (DisableSetFocus.IsChecked == false)
    {
     if (SetFocusTextBox2.IsChecked == false) TextBox1.Focus();
     else TextBox2.Focus();
    }
   }
  }

示例

该示例具有主要内容,其中包含许多控件,包括两个CheckBox控件。其中一个CheckBox控件将启用焦点设置,另一个会将焦点从第一个TextBox更改为第二个TextBox。 当单击“显示覆盖层Button时,将出现一个带有Panel和一个“关闭Button的控件。 此Panel将完全覆盖Window中的其他控件,因此只能单击“关闭Button。 单击此Button后,覆盖层Control将消失。 如果选中“禁用焦点CheckBox,则不会将焦点设置到窗体上的任何Control。 但是,如果未选中IsChecked,则焦点将出现在第一个或第二个TextBox中,具体取决于是否选中“聚焦到文本框 2(否则为文本框 1)CheckBoxIsChecked

初始屏幕

单击“显示覆盖层”按钮后的屏幕

如果单击“显示备用内容Button,则带有TextBoxButtonPanel将覆盖除Button控件以外的所有控件。 如果单击“显示覆盖层Button,则会出现带有单个Button的相同覆盖层Panel,并且如果未选择“禁用焦点CheckBox,则焦点将位于TextBox上。 否则,将没有焦点。

单击“显示备用内容”按钮后的屏幕

单击“显示备用内容”,然后单击“显示覆盖层”按钮后的屏幕

关注点

这种连接到现有DependencyProperties的处理程序的能力应该被记住,因为它为执行非常规任务提供了很多选择。

我还考虑了如何将其变成一种行为,并计划研究该选项。

历史

  • 2016 年 5 月 5 日:初始版本
  • 2016 年 5 月 16 日:向文章和代码添加了PriorityBinding以进行比较
  • 2016 年 5 月 21 日:更新了代码以包含ContentPresentor设置焦点示例
在 ContentPresenter 中捕获内容更改 - CodeProject - 代码之家
© . All rights reserved.