Click here to Skip to main content
15,880,967 members
Articles / Desktop Programming / WPF
Tip/Trick

WPF Disabled Items Behaviour

Rate me:
Please Sign up or sign in to vote.
5.00/5 (12 votes)
6 Aug 2016CPOL1 min read 8.7K   64   7   2
This tip presents a way to have disabled items in your ComboBox

Introduction

It was requested that some items in a ComboBox list would not be selectable. This proved to be a much more difficult task than I expected. IsHitTestVisible and IsEnabled for a control used in the ItemTemplate did not work.

Design

I initially started testing in the OnSelectionChanged event, and then moved to a generic, and finally a behaviour:

C#
 public class ComboBoxItemAvailableBehaviour
 {
  public static readonly DependencyProperty IsAvailableProperty =
   DependencyProperty.RegisterAttached("IsAvailable", typeof(Func<object,bool>),
    typeof(ComboBoxItemAvailableBehaviour), new UIPropertyMetadata(null, OnValueChanged));

  public static Func<object, bool> GetIsAvailable(Control o)
  {
   return (Func<object, bool>)o.GetValue(IsAvailableProperty);
  }

  public static void SetIsAvailable(Control o, Func<object, bool> value)
  {
   o.SetValue(IsAvailableProperty, value);
  }

  private static void OnValueChanged(DependencyObject dependencyObject,
   DependencyPropertyChangedEventArgs e)
  {
   var comboBox = dependencyObject as ComboBox;
   if (comboBox != null)
   {
    comboBox.SelectionChanged -= ComboBox_SelectionChanged;
    comboBox.SelectionChanged += ComboBox_SelectionChanged;
   }
  }

  private static void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
  {
   var comboBox = (ComboBox)sender;
   if (e.AddedItems.Count > 0)
   {
    if (! GetIsAvailable(comboBox).Invoke(e.AddedItems[0]))
     if (e.RemovedItems.Count > 0)
      comboBox.SelectedItem = e.RemovedItems[0];
     else
      comboBox.SelectedIndex = -1;
   }
  }
 }

The DependencyProperty is of type Func<object,bool> so that any value can be passed to the behavior for evaluation. This Func<object,bool> is used to determine if the DataContext for the particular ComboBoxItem is selectable. When a new Func<object,bool> is provided, a subscription is made to the SelectionChanged event. When the selection is changed, checking for any added item is made, and if there is an added item, the function is called to check if this is an item is available. If it is not available, the change is backed out. This could mean that the SelectedItem is set back to the removed item, or the SelectedIndex is set to -1 if there are no removed items.

In the OnValueChanged method, before there is s subscription to the SelectionChanged event, there is a remove to ensure that there is not a multiple subscription to the event. Probably unnessary since this behaviour will probably not change, but method to be used to check if the item is availble could be updated.

Using the Code

To use the code, a property of type Func<object, bool> has to be in the DataContext. This is bound to the IsAvailable DependencyProperty of the behaviour:

XML
<ComboBox Width="100"
          HorizontalAlignment="Center"
          VerticalAlignment="Center" SelectionChanged="Selector_OnSelectionChanged"
     local:ComboBoxItemAvailableBehaviour.IsAvailable="{Binding IsAvailable}"
          ItemsSource="{Binding ItemsSource}"
          SelectedItem="{Binding SelectedItem}">
 <ComboBox.ItemTemplate>
  <DataTemplate DataType="{x:Type local:ComboBoxItemViewModel}">
   <TextBlock Foreground="{Binding IsAvailable,
                                   Converter={local:IsTrueConverter},
                                   ConverterParameter=Black:Gray}"
              IsHitTestVisible="False"
              Text="{Binding Text}" />
  </DataTemplate>
 </ComboBox.ItemTemplate>
</ComboBox>

History

  • 08/05/2016: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Clifford Nelson Consulting
United States United States
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.

Comments and Discussions

 
SuggestionSubscribe once Pin
VMAtm14-Aug-16 16:23
VMAtm14-Aug-16 16:23 
AnswerRe: Subscribe once Pin
Clifford Nelson14-Aug-16 18:54
Clifford Nelson14-Aug-16 18:54 
Thanks for reminding me. I did see that it was an issue, but would not affect where I was using it, so I forgot I needed to fix the problem.

modified 15-Aug-16 1:01am.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.