This example shows how to handle two lists for selecting items. One showing selected items, the other showing remaining options available (minus the selected options).
As you select items from the ComboBox, they are moved to the "Selected" listbox. Selected items have a remove button, which returns the item to the "select" Combo.
You can download the sample project here : http://code.msdn.microsoft.com/How-to-manage-availablesele-175b1682
This sample project shows two methods of coding this solution, firstly using MVVM architecture, then using plain old code behind.
Fisrtly, let's look at the nicer way to do this. Example 1 has just one line in the code-behind:
DataContext =
new
ViewModel.Example1ViewModel();
Then the ViewModel takes over. Everything is therefore done with bindings in Example1Window.xaml, as the ViewModel does not know of any controls. Here is the 'available' listbox:
<
ComboBox
ItemsSource
=
"{Binding UnselectedPeople}"
DisplayMemberPath
"Name"
Margin
"0,0,10,0"
helpers:EventToCommand.Event
"ComboBox.SelectionChanged"
helpers:EventToCommand.CommandParameter
"{Binding SelectedItem, RelativeSource={RelativeSource Self}}"
helpers:EventToCommand.Command
"{Binding SelectPersonCommand}"
/>
Notice I am using the SelectionChanged event rather than binding to SelectedItem. This is because in practice, SelectedItem is not cleared when the actual item is removed from the underlying collection, which caused binding issues in later tasks. Instead I deploy an EventToCommand behaviour to convert SelectionChanged into a Command from the ViewModel.
The EventToCommand and RelayCommand shown in this project are from my MVVMXL sample project.
The 'selected' listbox is as follows:
ListBox
"{Binding SelectedPeople}"
Grid.Row
"1"
Background
"{x:Null}"
BorderThickness
"0"
FontWeight
"Bold"
ItemTemplate
"{StaticResource SelectedPersonItemTemplate}"
ItemContainerStyle
"{StaticResource StretchedItemContainer}"
SelectedPeople is an ObservableCollection, so any changes are reflected back in the UI, but UnselectedPeople is a calculated property, that needs triggering (manually calling RaisepropertyChanged) every time an option is selected or removed.
private
void
DoSelectPerson(
object
parameter)
{
var person = parameter
as
Person;
if
(person ==
null
)
return
;
SelectedPeople.Add(person);
RaisePropertyChanged(
"UnselectedPeople"
);
//Regenerate the list
}
DoUnselectPerson(
SelectedPeople.Remove(person);
public
List<Person> UnselectedPeople
get
(SelectedPeople.Count == 0)
AllPeople;
AllPeople.Except(SelectedPeople).ToList();
Example2Window()
InitializeComponent();
AllPeople =
List<Person>();
for
(var i = 0; i < 10; i++)
AllPeople.Add(
Person(i,
"Person_"
+ i));
lstSelected.ItemsSource = SelectedPeople =
ObservableCollection<Person>();
LoadUnselectedCombo();
ComboBox_SelectionChanged(
sender, SelectionChangedEventArgs e)
var person = cmbUnselected.SelectedItem
(person !=
Button_Click(
sender, RoutedEventArgs e)
var button = sender
Button;
var person = button.DataContext
(button !=
&& person !=
LoadUnselectedCombo()
cmbUnselected.ItemsSource = UnselectedPeople;
XAML guy edited Original. Comment: added
XAML guy edited Revision 1. Comment: title
Can you give this one title casing and a title that isn't like three sentences?
Great article!
Thanks!
In case you haven't heard yet...
Congratulations on winning a medal! blogs.technet.com/.../technet-guru-awards-june-2013.aspx