#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.
Cheers!
AJ