Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Capturing a Content Change in a ContentPresenter

0.00/5 (No votes)
5 May 2016 1  
This presents a way to capture a PropertyChanged on a DependencyObject, in this case to capture when the Content on a ContentPresenter changes and setting focus.

Introduction

I had a requirement to set the initial focus on a TextBox but there was a catch. When the UserControl that contained the TextBox appeared, there was always a UserControl in the foreground that was providing busy information, or an error condition. Therefore the normal setting of focus on initialization or loading did not work. To make things even worse, I designed the main Window to use ContentPresenters whose Content was used to determine the DataTemplate to use for the ViewModel associated with the Content.

The Control

The code used to catch the change in the Content of a ContentPresenter is done by creating a new Control derived from the ContentPresenter:

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;
}

Then all that is needed in the main Window (or UserControl) is to associate an event handler to the ContentChanged event of this Control:

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

In the case of the sample with this article, I simply check if the Content for the ActionableContentPresenter is null, and if it is, the focus can be set:

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();
  }
 }
}

The Sample

The sample has a the main content which contains a number of controls, including two CheckBox controls. One of the CheckBox controls will enable the set focus and the other will changes the focus from the first TextBox to the second TextBox. When the "Show Overlay" Button is clicked, and control with a Panel with a single "Close" Button will appear. This Panel will completely overlay the other controls in the Window so only the "Close" Button can be clicked. When this Button is clicked, the overlay Control will disappear. If the "Disable Focus" CheckBox is selected, there will be no focus set to any Control on the form. However, if it is not IsChecked, then the focus will appear in either the first or the second TextBox, depending on if the "Focus on TextBox 2 (otherwise TextBox 1)" CheckBox is IsChecked.

Initial Screen

Screen after "Show Overlay" button clicked

If the "Show Alternate Content" Button is Clicked, then a Panel with a TextBox and Button will overlay all the Controls except the Button controls. If the "Show Overlay" Button is clicked, the same overlay Panel with a single Button will appear, and, if the "Disable Focus" CheckBox is not selected, the focus will be on the TextBox. Otherwise there will be no focus.

Screen after "Show Alternate Content" button is clicked

Screen after "Show Alternate Content" and then "Show Overlay" buttons are clicked

Points of Interest

This ability to connect to handlers to existing DependencyProperties should be remembered because it opens up a lot of options on doing unconventional tasks.

I have also thought about how to make this a behavior, and plan to investigate the option.

History

  • 05/05/2016: Initial version
  • 05/16/2016: Added PriorityBinding to article and code for comparison
  • 05/21/2016: Updated code to include a ContentPresentor set focus example

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here