Click here to Skip to main content
15,860,859 members
Articles / Desktop Programming / WPF
Article

WPF CheckListBox/RadioListBox + CheckComboBox/RadioComboBox

Rate me:
Please Sign up or sign in to vote.
4.63/5 (17 votes)
30 Oct 2008CPOL3 min read 71K   2.4K   40   13
Intended for LOB applications: WPF CheckListBox/RadioListBox with bound datatype.

Introduction

In LOB applications, we have to design many windows, and many entities are bound to entry fields. Also, sometimes, there are enums or bool[] arrays to be used. Therefore, I had a look at the chances I got to bind some user control to an enum data type. There is no CheckListBox as in WinForms, and WPF shows the whole power when a ListBox has to be customized to a CheckListBox. A template-style will do for that more or less. It is more difficult when the CheckListBox should be bound to a flagged enum or is a RadioListBox.

WPFCheckListBox_Sample.png

What I wanted to achieve

In the case of showing all enum items to the user, I wanted to do the following:

  • drop a control from the toolbox on the form
  • set a binding to the entity, specifying the property name

With declaring the property in the business object as an enum type, I already do everything beforehand, so I do not have to think again about the enum items and setting the ItemSource, and so on.

Using the code

Like the specs, you just drop the desired control onto the form and set the binding. In the sample, all the necessary parts are contained to show the functionality:

XML
<clb:RadioListBox Name="listBoxType" 
                  CheckedValue="{Binding PropType, Mode=TwoWay}"/>

<clb:CheckListBox Name="listBoxFeature"
                  CheckedValue="{Binding PropFeature, Mode=TwoWay}"/>

The CheckedValue dependency property holds the bound data property from the entity. It is important to specify that the binding is TwoWay.

Sometimes, you don't have an enum data type but a bool[] array or anything else. In this case, there is no way to find out what the items to appear in the selection list are. So, you must somehow declare and propagate the collection to the control. You can do this in the code or in XAML. In any case, this has to be done before the first binding occurs. Here is a sample in XAML:

XML
<Window.Resources>
    <coll:ArrayList x:Key="actionList">
        <clb:CheckItem KeyValue="0" Display="action 0"/>
        <clb:CheckItem KeyValue="1" Display="action 1"/>
        <clb:CheckItem KeyValue="2" Display="action 2"/>
    </coll:ArrayList>

    <coll:ArrayList x:Key="arrayList">
        <clb:CheckItem KeyValue="0" Display="item 0"/>
        <clb:CheckItem KeyValue="1" Display="item 1"/>
        <clb:CheckItem KeyValue="2" Display="item 2"/>
        <clb:CheckItem KeyValue="3" Display="item 3"/>
    </coll:ArrayList>
</Window.Resources>

<clb:RadioListBox Name="listBoxAction" 
                  CheckListArray="{StaticResource actionList}" 
                  CheckedValue="{Binding PropAction, Mode=TwoWay}" />

<clb:CheckListBox Name="listBoxArray"
                  CheckListArray="{StaticResource arrayList}" 
                  CheckedValue="{Binding PropArray, Mode=TwoWay}"/>

The CheckListArray holds the collection to be shown in the list. Specify the KeyValue if you want the chosen value as, e.g., an integer.

What is happening when running

In the underlying base class of the CheckListBox and RadioListBox, the DataContextChanged is used to intercept on a binding to the bound property. In this case, the CheckedValue.OnDataContextChanged, the type of the bound property, is evaluated, and either a prepared collection, or the items of the enum are bound to the ItemSource of the ListBox. To keep track of the changes, a ViewModel (I call it this way, might not meet the name) is created to control the ListBox and the bound property.

This class is important, the enum could be of various types: byte, int, uint, long, ulong... They all work neat because the ViewModel uses a UInt64 array of values to keep track of the enumeration values. The corresponding data types are boxed/unboxed accordingly.

The [Flags] attribute is very important on an enum data type. Without this, only one choice can be checked, and even a CheckListBox is used.

If someone wants to do all this before the first binding, the method CreateViewModel could be called manually by specifying the corresponding type.

C#
public void CreateViewModel(Type boundType)
{
   if (boundType==null)
   {
      return;
   }
   if (this.CheckViewModel == null || this.CheckViewModel.BoundType != boundType)
   {
      Type _viewBase = typeof(CheckViewModel<>);
      Type _viewType = _viewBase.MakeGenericType(boundType);

      this.CheckViewModel = (ICheckViewModel)Activator.CreateInstance(_viewType);
      this.CheckViewModel.HostParent = this;
      this.CheckViewModel.IsRadioMode = this.isRadioMode;  // is passed by constructor

      if (this.CheckListArray != null)
      {
          List<CheckItem> _itemList = new List<CheckItem>();
          foreach (CheckItem _checkItem in this.CheckListArray)
          {
             _itemList.Add(_checkItem);
          }
          this.CheckViewModel.CheckItems = _itemList;
      }
      else
      {
          this.CheckViewModel.InitDiscovery();
      }
   }
   if (this.CheckViewModel != null && this.ItemsSource == null)
   {
      this.ItemsSource = this.CheckViewModel.CheckItems;
      this.DisplayMemberPath = "Display";
      this.SelectedValuePath = "KeyValue";
      this.SelectionMode = SelectionMode.Single;
   }
}

Overview

The CheckModelView is encapsulated in the CheckListBoxBase. From this base class, the CheckListBox and the RadioListBox are derived. The main reason for this is the different template they use for the ListBox:

CheckViewModel.png

So maybe, it helps someone, or some real WPF-experts (you name them) might come up with a better solution. Cheers!

History

  • 15.10.2008 > Initial publication.
  • 31.10.2008 > Update: CheckComboBox and RadioComboBox.

License

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


Written By
Software Developer
Switzerland Switzerland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questiondatasource Pin
Fernando E. Braz3-Jun-13 8:59
Fernando E. Braz3-Jun-13 8:59 
QuestionHow to customize clb:CheckItem? Pin
Masupilamix3-Dec-11 5:02
Masupilamix3-Dec-11 5:02 
AnswerRe: How to customize clb:CheckItem? Pin
christoph brändle6-Dec-11 2:55
christoph brändle6-Dec-11 2:55 
QuestionHow to bind date to CheckListArray?Not using StaticResource. Pin
artan00810-May-10 17:35
artan00810-May-10 17:35 
AnswerRe: How to bind date to CheckListArray?Not using StaticResource. Pin
Member 32246501-Jun-10 0:14
Member 32246501-Jun-10 0:14 
GeneralGet the following error Pin
eve1236-Feb-10 20:45
eve1236-Feb-10 20:45 
GeneralRe: Get the following error Pin
christoph brändle8-Feb-10 23:23
christoph brändle8-Feb-10 23:23 
GeneralLike it Pin
Sacha Barber25-Oct-08 21:56
Sacha Barber25-Oct-08 21:56 
GeneralRe: Like it Pin
christoph brändle31-Oct-08 11:28
christoph brändle31-Oct-08 11:28 
GeneralRe: Like it Pin
Sacha Barber31-Oct-08 22:18
Sacha Barber31-Oct-08 22:18 
GeneralRe: Like it Pin
christoph brändle1-Nov-08 3:53
christoph brändle1-Nov-08 3:53 
GeneralRe: Like it Pin
Sacha Barber1-Nov-08 4:13
Sacha Barber1-Nov-08 4:13 
GeneralTimely Work Pin
Kavan Shaban25-Oct-08 1:12
Kavan Shaban25-Oct-08 1:12 

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.