#Telerik : Complex Drop Down Boxes

Okay, so Telerik makes a fabulous suite of tools which include the RadComboBox control. Now if we want to take our previous example of a list of people the combobox works very well for selecting a list of items as shown in the the example below.

 

Now there is nothing fancy going on here. We just took some simple code to populate a RadComboBox with a list of people.

   1: <telerik:RadComboBox x:Name="HereList" Height="43" HorizontalAlignment="Left" 

   2:                Margin="12,50,0,0"  VerticalAlignment="Top" Width="335">

   3:           <telerik:RadComboBox.ItemsPanel>

   4:               <ItemsPanelTemplate>

   5:                   <StackPanel cal:Action.TargetWithoutContext="{Binding}" />

   6:               </ItemsPanelTemplate>

   7:           </telerik:RadComboBox.ItemsPanel>

   8:           <telerik:RadComboBox.ItemContainerStyle>

   9:               <Style TargetType="{x:Type ListBoxItem}">

  10:                   <Setter Property="cal:Message.Attach" 

  11:                           Value="[Event MouseDoubleClick] = [Action MoveToThere($dataContext)]"/>

  12:               </Style>

  13:           </telerik:RadComboBox.ItemContainerStyle>

  14:           <telerik:RadComboBox.ItemTemplate>

  15:               <DataTemplate>

  16:                       <Grid Margin="2" >

  17:                           <Grid.RowDefinitions>

  18:                               <RowDefinition/>

  19:                               <RowDefinition/>

  20:                           </Grid.RowDefinitions>

  21:                           <StackPanel Orientation="Horizontal">

  22:                               <TextBlock Text="{Binding FirstName}"/>

  23:                               <TextBlock Text="{Binding LastName}"/>

  24:                           </StackPanel>

  25:                           <TextBlock Grid.Row="1" Text="{Binding City}" FontWeight="SemiBold" />

  26:                       </Grid>

  27:               </DataTemplate>

  28:           </telerik:RadComboBox.ItemTemplate>

  29:       </telerik:RadComboBox>

 

Now what happens if I need something a little more complex? Like say I want to have the combobox display something like the following…

Selected Person #1

Selected Person #2

———– Line ———-

Unselected Person #1

Unselected Person #2

 

What more….what if I wanted the two lists to be totally separate data templates?! Fortunately, even though the RadComboBox doesn’t necessarily support this Telerik provides us with another control know as the RadDropDownButton. Now stay with me on this….. The RadDropDownButton will work for us because instead of constraining us with ListBoxItems is provides us with a DropDownContent area that we can pretty much load up with whatever content our heart desires! So let’s do a little ‘fanaggling’ with our code. To separate out the two lists … we’ll start in the model first…. just so you can see what the backend is doing ….

   1: namespace SilverwingTech.SQLDoxs.ViewModels

   2: {

   3:     using Caliburn.Micro;

   4:     using System.Collections.Generic;

   5:     using System.Collections.ObjectModel;

   6:  

   7:     public class ShellViewModel : PropertyChangedBase

   8:     {

   9:  

  10:  

  11:         private List<Person> persons;

  12:  

  13:         public ShellViewModel()

  14:         {

  15:               persons = new List<Person>();

  16:               persons.Add(new Person(){ FirstName="Arie", LastName="Jones", City="Indianapolis"});

  17:               persons.Add(new Person(){ FirstName="Brett", LastName="Canova", City="Indianapolis"});

  18:               persons.Add(new Person(){ FirstName="Justin", LastName="Bieber", City="Somewhere in Canada"});

  19:               persons.Add(new Person(){ FirstName="Steve", LastName="Jones", City="Denver"});

  20:               persons.Add(new Person(){ FirstName="Dennis", LastName="Miller", City="Santa Barbara"});

  21:               persons.Add(new Person() { FirstName = "David", LastName = "Letterman", City = "New York" });

  22:  

  23:               NonSelectedList = new ObservableCollection<Person>(persons);

  24:               SelectedList = new ObservableCollection<Person>();

  25:  

  26:         }

  27:  

  28:  

  29:         private ObservableCollection<Person> _NonSelectedList;

  30:         public ObservableCollection<Person> NonSelectedList

  31:         {

  32:             get

  33:             {

  34:                 return _NonSelectedList;

  35:             }

  36:             set

  37:             {

  38:                 _NonSelectedList = value;

  39:                 NotifyOfPropertyChange(() => NonSelectedList);

  40:             }

  41:         }

  42:  

  43:         private ObservableCollection<Person> _SelectedList;

  44:         public ObservableCollection<Person> SelectedList

  45:         {

  46:             get

  47:             {

  48:                 return _SelectedList;

  49:             }

  50:             set

  51:             {

  52:                 _SelectedList = value;

  53:                 NotifyOfPropertyChange(() => SelectedList);

  54:             }

  55:         }

  56:  

  57:  

  58:         public void MoveToSelected(Person person)

  59:         {

  60:             NonSelectedList.Remove(person);

  61:             SelectedList.Add(person);

  62:         }

  63:  

  64:         public void MoveToNonSelected(Person person)

  65:         {

  66:             NonSelectedList.Add(person);

  67:             SelectedList.Remove(person);

  68:         }

  69:  

  70:     }

  71:  

  72:     public class Person: PropertyChangedBase

  73:     {

  74:         private string _FirstName;

  75:         public string FirstName

  76:         {

  77:             get { return _FirstName; }

  78:             set

  79:             {

  80:                 _FirstName = value;

  81:                 NotifyOfPropertyChange(() => FirstName);

  82:                 

  83:             }

  84:         }

  85:  

  86:         private string _LastName;

  87:         public string LastName

  88:         {

  89:             get { return _LastName; }

  90:             set

  91:             {

  92:                 _LastName = value;

  93:                 NotifyOfPropertyChange(() => LastName);

  94:             }

  95:         }

  96:  

  97:         private string _City;

  98:         public string City

  99:         {

 100:             get { return _City; }

 101:             set

 102:             {

 103:                 _City = value;

 104:                 NotifyOfPropertyChange(() => City);

 105:             }

 106:         }

 107:  

 108:         

 109:         

 110:         

 111:  

 112:     }

 113: }

 

So now we need to change out control to be a set of listboxes wrapped in a RadDropDownButton control. This follows nearly the same format as my post on Caliburn.Micro . So if you have trouble following along then feel free to reference that post as a precursor to this one.

   1: <Window x:Class="SilverwingTech.SQLDoxs.Views.ShellView"

   2:         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   3:         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   4:         xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"

   5:         xmlns:cal="http://www.caliburnproject.org"

   6:         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

   7:         Title="MainWindow" Height="350" Width="525">

   8:     <Grid>

   9:         <telerik:RadDropDownButton Width="177"

  10:                                   Margin="10 5 10 5"

  11:                                   Content="Select People(s)" Height="43"

  12:                                   DropDownHeight="400"

  13:                                        >

  14:             <telerik:RadDropDownButton.DropDownContent>

  15:                 <ScrollViewer CanContentScroll="True">

  16:                     <Grid>

  17:                         <Grid.RowDefinitions>

  18:                             <RowDefinition/>

  19:                             <RowDefinition Height="20"/>

  20:                             <RowDefinition/>

  21:                         </Grid.RowDefinitions>

  22:                         <ListBox ItemsSource="{Binding SelectedList}" MinHeight="20" HorizontalAlignment="Left" 

  23:                  Margin="12,50,0,0"  VerticalAlignment="Top" MinWidth="175">

  24:                             <ListBox.ItemsPanel>

  25:                                 <ItemsPanelTemplate>

  26:                                     <StackPanel cal:Action.TargetWithoutContext="{Binding}" />

  27:                                 </ItemsPanelTemplate>

  28:                             </ListBox.ItemsPanel>

  29:                             <ListBox.ItemContainerStyle>

  30:                                 <Style TargetType="{x:Type ListBoxItem}">

  31:                                     <Setter Property="cal:Message.Attach" 

  32:                             Value="[Event MouseDoubleClick] = [Action MoveToNonSelected($dataContext)]"/>

  33:                                 </Style>

  34:                             </ListBox.ItemContainerStyle>

  35:                             <ListBox.ItemTemplate>

  36:                                 <DataTemplate>

  37:                                     <Grid Margin="2" >

  38:                                         <Grid.RowDefinitions>

  39:                                             <RowDefinition/>

  40:                                             <RowDefinition/>

  41:                                         </Grid.RowDefinitions>

  42:                                         <StackPanel Orientation="Horizontal">

  43:                                             <TextBlock Text="{Binding FirstName}"/>

  44:                                             <TextBlock Text="{Binding LastName}"/>

  45:                                         </StackPanel>

  46:                                         <TextBlock Grid.Row="1" Text="{Binding City}" FontWeight="SemiBold" />

  47:                                     </Grid>

  48:                                 </DataTemplate>

  49:                             </ListBox.ItemTemplate>

  50:                         </ListBox>

  51:                         <Separator Grid.Row="1"/>

  52:                         <ListBox ItemsSource="{Binding NonSelectedList}" MinHeight="20" HorizontalAlignment="Left" Grid.Row="2"   Margin="12,50,0,0"  VerticalAlignment="Top" MinWidth="175">

  53:                             <ListBox.ItemsPanel>

  54:                                 <ItemsPanelTemplate>

  55:                                     <StackPanel cal:Action.TargetWithoutContext="{Binding}" />

  56:                                 </ItemsPanelTemplate>

  57:                             </ListBox.ItemsPanel>

  58:                             <ListBox.ItemContainerStyle>

  59:                                 <Style TargetType="{x:Type ListBoxItem}">

  60:                                     <Setter Property="cal:Message.Attach" Value="[Event MouseDoubleClick] = [Action MoveToSelected($dataContext)]"/>

  61:                                 </Style>

  62:                             </ListBox.ItemContainerStyle>

  63:                             <ListBox.ItemTemplate>

  64:                                 <DataTemplate>

  65:                                     <Grid Margin="2" >

  66:                                         <Grid.RowDefinitions>

  67:                                             <RowDefinition/>

  68:                                             <RowDefinition/>

  69:                                         </Grid.RowDefinitions>

  70:                                         <StackPanel Orientation="Horizontal">

  71:                                             <TextBlock Text="{Binding FirstName}"/>

  72:                                             <TextBlock Text="{Binding LastName}"/>

  73:                                         </StackPanel>

  74:                                         <TextBlock Grid.Row="1" Text="{Binding City}" FontWeight="SemiBold" />

  75:                                     </Grid>

  76:                                 </DataTemplate>

  77:                             </ListBox.ItemTemplate>

  78:                         </ListBox>

  79:                     </Grid>

  80:                 </ScrollViewer>

  81:             </telerik:RadDropDownButton.DropDownContent>

  82:         </telerik:RadDropDownButton>

  83:     </Grid>

  84: </Window>

 

And if we look at the finished project then we can see that we have the functionality that we were looking for……

 

Pretty cool, if you need that non-standard UI implementation, that Telerik has provided a way to get it accomplished!

In case you need the project for reference you can download it below.. However, I am working with the 4.0 version of the 2011 Q1 SP1 so you may have some broken references depending on which version of Telerik you are using.

Complex Drop Down Project

 

Cheers!

AJ