Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It's not graceful or polished, but here is a workable sample. If I made this polished I would have implemented true MVVM, but as a sample, this will get you started.</p> <p>XAML:</p> <pre><code>&lt;Window x:Class="TwoListboxes.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="800"&gt; &lt;Grid&gt; &lt;Grid.ColumnDefinitions&gt; &lt;ColumnDefinition Width="*" /&gt; &lt;ColumnDefinition Width="120" /&gt; &lt;ColumnDefinition Width="*" /&gt; &lt;/Grid.ColumnDefinitions&gt; &lt;ListBox x:Name="List1" Grid.Column="0" Height="200" Margin="10" SelectionMode="Multiple" ItemsSource="{Binding Path=Collection1}"&gt; &lt;ListBox.ItemTemplate&gt; &lt;DataTemplate&gt; &lt;TextBlock Text="{Binding Path=Name}" /&gt; &lt;/DataTemplate&gt; &lt;/ListBox.ItemTemplate&gt; &lt;/ListBox&gt; &lt;StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"&gt; &lt;Button Content="&amp;gt;" Width="60" Click="MoveRightEvent" /&gt; &lt;Button Content="&amp;gt;&amp;gt;" Width="60" Click="MoveAllRightEvent" /&gt; &lt;Button Content="&amp;lt;&amp;lt;" Width="60" Click="MoveAllLeftEvent" /&gt; &lt;Button Content="&amp;lt;" Width="60" Click="MoveLeftEvent" /&gt; &lt;/StackPanel&gt; &lt;ListBox x:Name="List2" Grid.Column="2" Height="200" Margin="10" ItemsSource="{Binding Path=Collection2}"&gt; &lt;ListBox.ItemTemplate&gt; &lt;DataTemplate&gt; &lt;TextBlock Text="{Binding Path=Name}" /&gt; &lt;/DataTemplate&gt; &lt;/ListBox.ItemTemplate&gt; &lt;/ListBox&gt; &lt;/Grid&gt; &lt;/Window&gt; </code></pre> <p>The code-behind:</p> <pre><code>/// &lt;summary&gt; /// Interaction logic for MainWindow.xaml /// &lt;/summary&gt; public partial class MainWindow : Window { #region Members private readonly ViewModel&lt;TrackerItem&gt; _vm; #endregion public MainWindow() { // Get viewmodel and set context _vm = new ViewModel&lt;TrackerItem&gt;(); _vm.Collection1 = new ObservableCollection&lt;TrackerItem&gt; { new TrackerItem { Name = "Item1", Value = "1"}, new TrackerItem { Name = "Item2", Value = "2"}, new TrackerItem { Name = "Item3", Value = "3"}, new TrackerItem { Name = "Item4", Value = "4"}, new TrackerItem { Name = "Item5", Value = "5"}, new TrackerItem { Name = "Item6", Value = "6"}, new TrackerItem { Name = "Item7", Value = "7"}, new TrackerItem { Name = "Item8", Value = "8"}, new TrackerItem { Name = "Item9", Value = "9"}, new TrackerItem { Name = "Item10", Value = "10"} }; this.DataContext = _vm; // Initialize UI InitializeComponent(); } /// &lt;summary&gt; /// Moves selected items in a list from one collection to another. /// &lt;/summary&gt; /// &lt;param name="list"&gt;&lt;/param&gt; /// &lt;param name="source"&gt;&lt;/param&gt; /// &lt;param name="destination"&gt;&lt;/param&gt; private void MoveItems(ListBox list, ObservableCollection&lt;TrackerItem&gt; source, ObservableCollection&lt;TrackerItem&gt; destination) { if (list.SelectedItems.Count &gt; 0) { // List for items to be removed. var hitList = new List&lt;TrackerItem&gt;(); // Move items foreach (var selectedItem in list.SelectedItems) { var item = selectedItem as TrackerItem; if (item != null) { // Tag item for removal hitList.Add(item); // Check if item is in target list var targetList = (from p in destination where p == item select p).ToList(); // Add to destination if (!targetList.Any()) { destination.Add(item); } } } // Remove items foreach (var hitItem in hitList) { // Remove item source.Remove(hitItem); } } } /// &lt;summary&gt; /// Moves all items from one list to another. /// &lt;/summary&gt; /// &lt;param name="source"&gt;&lt;/param&gt; /// &lt;param name="destination"&gt;&lt;/param&gt; private void MoveAllItems( ObservableCollection&lt;TrackerItem&gt; source, ObservableCollection&lt;TrackerItem&gt; destination) { // List for items to be removed. var hitList = new List&lt;TrackerItem&gt;(); // Move items foreach (var item in source) { if (item != null) { // Tag item for removal hitList.Add(item); // Check if item is in target list var targetList = (from p in destination where p == item select p).ToList(); // Add to destination if (!targetList.Any()) { destination.Add(item); } } } // Remove items foreach (var hitItem in hitList) { // Remove item source.Remove(hitItem); } } /// &lt;summary&gt; /// Click event: moves selected items to the right. /// &lt;/summary&gt; /// &lt;param name="sender"&gt;&lt;/param&gt; /// &lt;param name="e"&gt;&lt;/param&gt; private void MoveRightEvent(object sender, RoutedEventArgs e) { MoveItems(List1, _vm.Collection1, _vm.Collection2); } /// &lt;summary&gt; /// Click event: moves all items to the right.. /// &lt;/summary&gt; /// &lt;param name="sender"&gt;&lt;/param&gt; /// &lt;param name="e"&gt;&lt;/param&gt; private void MoveAllRightEvent(object sender, RoutedEventArgs e) { MoveAllItems(_vm.Collection1, _vm.Collection2); } /// &lt;summary&gt; /// Click event: moves all items to the left. /// &lt;/summary&gt; /// &lt;param name="sender"&gt;&lt;/param&gt; /// &lt;param name="e"&gt;&lt;/param&gt; private void MoveAllLeftEvent(object sender, RoutedEventArgs e) { MoveAllItems(_vm.Collection2, _vm.Collection1); } /// &lt;summary&gt; /// Click event: moves selected items to the left. /// &lt;/summary&gt; /// &lt;param name="sender"&gt;&lt;/param&gt; /// &lt;param name="e"&gt;&lt;/param&gt; private void MoveLeftEvent(object sender, RoutedEventArgs e) { MoveItems(List2, _vm.Collection2, _vm.Collection1); } } </code></pre> <p>The ViewModel:</p> <pre><code>public class ViewModel&lt;T&gt; : INotifyPropertyChanged { #region Properties private ObservableCollection&lt;T&gt; _collection1; /// &lt;summary&gt; /// This is the first collection. /// &lt;/summary&gt; public ObservableCollection&lt;T&gt; Collection1 { get { return _collection1; } set { if (value != _collection1) { _collection1 = value; NotifyPropertyChanged("Collection1"); } } } private ObservableCollection&lt;T&gt; _collection2; /// &lt;summary&gt; /// This is the second collection. /// &lt;/summary&gt; public ObservableCollection&lt;T&gt; Collection2 { get { return _collection2; } set { if (value != _collection2) { _collection2 = value; NotifyPropertyChanged("Collection2"); } } } #endregion #region Constructors /// &lt;summary&gt; /// Default constructor. /// &lt;/summary&gt; public ViewModel() { // Create initial collections. // Populate first collection with sample data _collection1 = new ObservableCollection&lt;T&gt;(); // Seconf collection is empty _collection2 = new ObservableCollection&lt;T&gt;(); } #endregion #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } #endregion } </code></pre> <p>TrackerItem</p> <pre><code>public class TrackerItem : INotifyPropertyChanged { private string _name; /// &lt;summary&gt; /// A name. /// &lt;/summary&gt; public string Name { get { return _name; } set { if (value != _name) { _name = value; NotifyPropertyChanged("Name"); } } } private string _value; /// &lt;summary&gt; /// A value. /// &lt;/summary&gt; public string Value { get { return _value; } set { if (value != _value) { _value = value; NotifyPropertyChanged("Value"); } } } #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } #endregion } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload