BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Presentation Foundation
.NET 4.0+

WPF Base Classes - Selector

The thirty-sixth part of the Windows Presentation Foundation Fundamentals tutorial looks at another WPF control base class. This article describes the Selector class, which is subclassed by controls that allow the user to select from a list of values.

Attached Events

The Selector type defines two attached events. In a similar manner to attached properties, these are events that can be raised for items other than the class that defines them. In the case of the Selected and Unselected events, they are made available by the Selector class to be raised for the items in the collection. Selected is raised when one of the items in the collection is selected. Unselected is raised when an item is deselected. As controls derived from Selector can include multiple selections, it is possible for many of these events to be raised by a single user action.

It is possible to add the two events to just a subset of the items in the displayed collection. However, for our demonstration let's add both events to every TabItem. Modify the XAML for the TabItems as follows. Note that the attached events are prefixed with the name of the class that defines them, "Selector".

<TabItem Header="Red" Background="Red"
    Selector.Selected="TabItem_Selected" Selector.Unselected="TabItem_Unselected"/>
<TabItem Header="Yellow" Background="Yellow"
    Selector.Selected="TabItem_Selected" Selector.Unselected="TabItem_Unselected"/>
<TabItem Header="Green" Background="Green"
    Selector.Selected="TabItem_Selected" Selector.Unselected="TabItem_Unselected"/>
<TabItem Header="Blue" Background="Blue"
    Selector.Selected="TabItem_Selected" Selector.Unselected="TabItem_Unselected"/>

We now need to add two methods to handle the events. The code below modifies the header of a tab when it is selected or deselected. Selecting adds an asterisk character (*), deselecting removes the asterisk. In this case any of the TabItems could raise either event so the code casts the sender argument to a TabItem in order to determine the source of the event.

private void TabItem_Selected(object sender, RoutedEventArgs e)
{
    var tab = sender as TabItem;
    string header = tab.Header.ToString();
    tab.Header = header + "*";
}

private void TabItem_Unselected(object sender, RoutedEventArgs e)
{
    var tab = sender as TabItem;
    string header = tab.Header.ToString();
    tab.Header = header.Substring(0, header.Length-1);
}

Try running the program to see the effect of the new code. Note that the SelectionChanged event still executes.

IsSelected Attached Property

The final Selector member that we'll consider in this article is an attached property. IsSelected is made available by Selector to each of the items in the displayable collection. It returns a Boolean value that is true if the item is selected and false if not. This property is ideal for use with LINQ queries, allowing you to quickly identify which items are selected and which are not.

The attached property is not particularly useful for TabControls, as the TabItem class includes its own IsSelected property. However, to demonstrate the attached property, let's use it from the code for the SelectionChanged event. The code below loops through all of the tabs, looking for one that is selected. The code uses the GetValue method to read the attached property's value. If the property returns true for a TabItem, the label is updated. The end result is the same as in previous examples.

private void MyTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    foreach (TabItem tab in MyTabControl.Items)
    {
        if ((bool)tab.GetValue(TabControl.IsSelectedProperty))
        {
            SelectedTabLabel.Content = tab.Header;
            SelectedTabLabel.Background = tab.Background;
        }
    }
}
16 November 2013