Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF中的数据绑定列表框子选择_C#_Wpf_User Controls_Listbox - Fatal编程技术网

C# WPF中的数据绑定列表框子选择

C# WPF中的数据绑定列表框子选择,c#,wpf,user-controls,listbox,C#,Wpf,User Controls,Listbox,好吧,我可能问了一个古老的问题,但我没有在任何一个问题中描述我的情景 我有一个可以包含多个子对象的项目。一个项目obejct可以有几个资源对象。我有一个ObservaleCollection,其中包含子OBEJCT的超集(在我的例子中是资源对象)。我在项目对象中还有另一个ObservableCollection,它包含现有的child 在WPF windows应用程序中向用户呈现此内容的最佳方式是什么?我还需要为他们提供一种方法来改变映射 我最初的想法是使用经典的双列表方法,使用两个列表框,但我

好吧,我可能问了一个古老的问题,但我没有在任何一个问题中描述我的情景

我有一个可以包含多个子对象的项目。一个项目obejct可以有几个资源对象。我有一个ObservaleCollection,其中包含子OBEJCT的超集(在我的例子中是资源对象)。我在项目对象中还有另一个ObservableCollection,它包含现有的child

在WPF windows应用程序中向用户呈现此内容的最佳方式是什么?我还需要为他们提供一种方法来改变映射

我最初的想法是使用经典的双列表方法,使用两个列表框,但我不确定单独操作视图层有多容易

[Resoure Collection]             [Resoure Collection in a Project]  
--------------------             ---------------------------------  
|Resource 1        |      >      |Resource 3                     |  
|Resource 2        |      >>     |Resource 4                     |  
|Resource 5        |      <      |                               |  
|Resource 6        |      <<     |                               |  
|Resource 7        |             |                               |  
[资源收集][项目中的资源收集]
--------------------             ---------------------------------  
|资源1 |>资源3 |
|资源2 |>>|资源4 |
|资源5 |<| |

|参考资料6 |它既不优雅也不优雅,但这里有一个可行的示例。如果我做得很好,我会实现真正的MVVM,但作为一个示例,这将帮助您开始

XAML:


背后的代码:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    #region Members

    private readonly ViewModel<TrackerItem> _vm;

    #endregion

    public MainWindow()
    {
        // Get viewmodel and set context
        _vm = new ViewModel<TrackerItem>();
        _vm.Collection1 = new ObservableCollection<TrackerItem>
            {
                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();
    }

    /// <summary>
    /// Moves selected items in a list from one collection to another.
    /// </summary>
    /// <param name="list"></param>
    /// <param name="source"></param>
    /// <param name="destination"></param>
    private void MoveItems(ListBox list,
        ObservableCollection<TrackerItem> source,
        ObservableCollection<TrackerItem> destination)
    {
        if (list.SelectedItems.Count > 0)
        {
            // List for items to be removed.
            var hitList = new List<TrackerItem>();

            // 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);
            }
        }
    }

    /// <summary>
    /// Moves all items from one list to another.
    /// </summary>
    /// <param name="source"></param>
    /// <param name="destination"></param>
    private void MoveAllItems(
        ObservableCollection<TrackerItem> source,
        ObservableCollection<TrackerItem> destination)
    {
        // List for items to be removed.
        var hitList = new List<TrackerItem>();

        // 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);
        }
    }

    /// <summary>
    /// Click event: moves selected items to the right.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveRightEvent(object sender, RoutedEventArgs e)
    {
        MoveItems(List1, _vm.Collection1, _vm.Collection2);
    }

    /// <summary>
    /// Click event: moves all items to the right..
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveAllRightEvent(object sender, RoutedEventArgs e)
    {
        MoveAllItems(_vm.Collection1, _vm.Collection2);
    }

    /// <summary>
    /// Click event: moves all items to the left.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveAllLeftEvent(object sender, RoutedEventArgs e)
    {
        MoveAllItems(_vm.Collection2, _vm.Collection1);
    }

    /// <summary>
    /// Click event: moves selected items to the left.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveLeftEvent(object sender, RoutedEventArgs e)
    {
        MoveItems(List2, _vm.Collection2, _vm.Collection1);
    }
}
//
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
#区域成员
私有只读视图模型_vm;
#端区
公共主窗口()
{
//获取viewmodel并设置上下文
_vm=新的ViewModel();
_vm.Collection1=新的ObservableCollection
{
新的TrackerItem{Name=“Item1”,Value=“1”},
新的TrackerItem{Name=“Item2”,Value=“2”},
新的TrackerItem{Name=“Item3”,Value=“3”},
新的TrackerItem{Name=“Item4”,Value=“4”},
新的TrackerItem{Name=“Item5”,Value=“5”},
新的TrackerItem{Name=“Item6”,Value=“6”},
新的TrackerItem{Name=“Item7”,Value=“7”},
新的TrackerItem{Name=“Item8”,Value=“8”},
新的TrackerItem{Name=“Item9”,Value=“9”},
新TrackerItem{Name=“Item10”,Value=“10”}
};
this.DataContext=\u vm;
//初始化用户界面
初始化组件();
}
/// 
///将列表中的选定项从一个集合移动到另一个集合。
/// 
/// 
/// 
/// 
私有项目(列表框列表,
可观测采集源,
可观察收集目的地)
{
如果(list.SelectedItems.Count>0)
{
//要删除的项目的列表。
var hitList=新列表();
//移动项目
foreach(列表中的变量selectedItem.SelectedItems)
{
var item=选择editem作为TrackerItem;
如果(项!=null)
{
//标记要删除的项目
点击列表。添加(项目);
//检查项目是否在目标列表中
var targetList=(来自目标中的p
其中p==项
选择p.ToList();
//添加到目的地
如果(!targetList.Any())
{
目的地。添加(项目);
}
}
}
//删除项目
foreach(hitList中的var hitItem)
{
//删除项目
来源。删除(项目);
}
}
}
/// 
///将所有项目从一个列表移动到另一个列表。
/// 
/// 
/// 
私有无效移动项(
可观测采集源,
可观察收集目的地)
{
//要删除的项目的列表。
var hitList=新列表();
//移动项目
foreach(源中的var项)
{
如果(项!=null)
{
//标记要删除的项目
点击列表。添加(项目);
//检查项目是否在目标列表中
var targetList=(来自目标中的p
其中p==项
选择p.ToList();
//添加到目的地
如果(!targetList.Any())
{
目的地。添加(项目);
}
}
}
//删除项目
foreach(hitList中的var hitItem)
{
//删除项目
来源。删除(项目);
}
}
/// 
///单击事件:将选定项目向右移动。
/// 
/// 
/// 
私有void MoveRightEvent(对象发送方,RoutedEventArgs e)
{
移动项目(列表1、_vm.Collection1、_vm.Collection2);
}
/// 
///单击事件:将所有项目向右移动。。
/// 
/// 
/// 
private void MoveAllRightEvent(对象发送方,RoutedEventArgs e)
{
MoveAllItems(_vm.Collection1,_vm.Collection2);
}
/// 
///单击事件:将所有项目向左移动。
/// 
/// 
/// 
私有void MoveAllLeftEvent(对象发送方,RoutedEventArgs e)
{
MoveAllItems(_vm.Collection2,_vm.Collection1);
}
/// 
///单击事件:将选定项目向左移动。
/// 
/// 
/// 
私有void MoveLeftEvent(对象发送方,RoutedEventArgs e)
{
移动项目(列表2,_vm.Collection2,_vm.Collection1);
}
}
V
/// <summary>
    /// Interaction logic for ItemsSelectionLists.xaml
    /// </summary>
    public partial class ItemsSelectionLists: UserControl
    {
        [Bindable(true)]

        internal ObservableCollection<TrackerItem> SourceList
        {
            get
            {
                return _vm.Collection1;
            }
            set
            {
                _vm.Collection1 = value;
            }
        }

        private readonly ViewModel _vm; 

        public ItemsSelectionLists()
        {
            this.InitializeComponent();
            _vm = new ViewModel();
            this.DataContext = _vm; 
        }
    }

    public class ViewModel : INotifyPropertyChanged
    {
        #region Properties

        private ObservableCollection<TrackerItem> _collection1;

        /// <summary> 
        /// This is the first collection. 
        /// </summary> 
        internal ObservableCollection<TrackerItem> Collection1
        {
            get
            {
                return _collection1;
            }

            set
            {
                if (value != _collection1)
                {
                    _collection1 = value;
                    NotifyPropertyChanged("Collection1");
                }
            }
        }

        private ObservableCollection<TrackerItem> _collection2;

        /// <summary> 
        /// This is the second collection. 
        /// </summary> 
        internal ObservableCollection<TrackerItem> Collection2
        {
            get
            {
                return _collection2;
            }

            set
            {
                if (value != _collection2)
                {
                    _collection2 = value;
                    NotifyPropertyChanged("Collection2");
                }
            }
        }

        #endregion

        #region Constructors

        /// <summary> 
        /// Default constructor. 
        /// </summary> 
        public ViewModel()
        {
            // Create initial collections. 

            // Populate first collection with sample data 
            _collection1 = new ObservableCollection<TrackerItem>();
            // Seconf collection is empty 
            _collection2 = new ObservableCollection<TrackerItem>();
        }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        #endregion
    }
<TabItem Header="Resource Allocation">
    <local:ItemsSelectionLists x:Name="ResourceSelection"/>
</TabItem>
ResourceSelection.SourceList = MainObject.Resources;
//error CS0029: Cannot implicitly convert type 'System.Collections.ObjectModel.ObservableCollection<TimeTracker.Resource>' to 'System.Collections.ObjectModel.ObservableCollection<TimeTracker.TrackerItem>'
<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">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="120" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <ListBox x:Name="List1" Grid.Column="0" 
                 Height="200" Margin="10" 
                 SelectionMode="Multiple"
                 ItemsSource="{Binding Path=Collection1}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=Name}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center">
            <Button Content="&gt;" Width="60" Click="MoveRightEvent" />
            <Button Content="&gt;&gt;" Width="60" Click="MoveAllRightEvent" />
            <Button Content="&lt;&lt;" Width="60" Click="MoveAllLeftEvent" />
            <Button Content="&lt;" Width="60" Click="MoveLeftEvent" />
        </StackPanel>

        <ListBox x:Name="List2" Grid.Column="2" 
                 Height="200" Margin="10" 
                 ItemsSource="{Binding Path=Collection2}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=Name}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    #region Members

    private readonly ViewModel<TrackerItem> _vm;

    #endregion

    public MainWindow()
    {
        // Get viewmodel and set context
        _vm = new ViewModel<TrackerItem>();
        _vm.Collection1 = new ObservableCollection<TrackerItem>
            {
                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();
    }

    /// <summary>
    /// Moves selected items in a list from one collection to another.
    /// </summary>
    /// <param name="list"></param>
    /// <param name="source"></param>
    /// <param name="destination"></param>
    private void MoveItems(ListBox list,
        ObservableCollection<TrackerItem> source,
        ObservableCollection<TrackerItem> destination)
    {
        if (list.SelectedItems.Count > 0)
        {
            // List for items to be removed.
            var hitList = new List<TrackerItem>();

            // 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);
            }
        }
    }

    /// <summary>
    /// Moves all items from one list to another.
    /// </summary>
    /// <param name="source"></param>
    /// <param name="destination"></param>
    private void MoveAllItems(
        ObservableCollection<TrackerItem> source,
        ObservableCollection<TrackerItem> destination)
    {
        // List for items to be removed.
        var hitList = new List<TrackerItem>();

        // 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);
        }
    }

    /// <summary>
    /// Click event: moves selected items to the right.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveRightEvent(object sender, RoutedEventArgs e)
    {
        MoveItems(List1, _vm.Collection1, _vm.Collection2);
    }

    /// <summary>
    /// Click event: moves all items to the right..
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveAllRightEvent(object sender, RoutedEventArgs e)
    {
        MoveAllItems(_vm.Collection1, _vm.Collection2);
    }

    /// <summary>
    /// Click event: moves all items to the left.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveAllLeftEvent(object sender, RoutedEventArgs e)
    {
        MoveAllItems(_vm.Collection2, _vm.Collection1);
    }

    /// <summary>
    /// Click event: moves selected items to the left.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveLeftEvent(object sender, RoutedEventArgs e)
    {
        MoveItems(List2, _vm.Collection2, _vm.Collection1);
    }
}
public class ViewModel<T> : INotifyPropertyChanged
{
    #region Properties

    private ObservableCollection<T> _collection1;

    /// <summary>
    /// This is the first collection.
    /// </summary>
    public ObservableCollection<T> Collection1
    {
        get { return _collection1; }

        set
        {
            if (value != _collection1)
            {
                _collection1 = value;
                NotifyPropertyChanged("Collection1");
            }
        }
    }

    private ObservableCollection<T> _collection2;

    /// <summary>
    /// This is the second collection.
    /// </summary>
    public ObservableCollection<T> Collection2
    {
        get { return _collection2; }

        set
        {
            if (value != _collection2)
            {
                _collection2 = value;
                NotifyPropertyChanged("Collection2");
            }
        }
    }

    #endregion

    #region Constructors

    /// <summary>
    /// Default constructor.
    /// </summary>
    public ViewModel()
    {
        // Create initial collections.

        // Populate first collection with sample data
        _collection1 = new ObservableCollection<T>();

        // Seconf collection is empty
        _collection2 = new ObservableCollection<T>();
    }

    #endregion

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    #endregion
}
public class TrackerItem : INotifyPropertyChanged
{
    private string _name;

    /// <summary>
    /// A name.
    /// </summary>
    public string Name
    {
        get { return _name; }

        set
        {
            if (value != _name)
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }

    private string _value;

    /// <summary>
    /// A value.
    /// </summary>
    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
}
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:TimeTracker"
         x:Class="TimeTracker.ItemsSelectionLists"
         x:Name="ItemsSelectionControl">
<UserControl.Resources>
    <local:DummyConverter x:Key="DummyConverter" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
    <Grid Background="#FFF9FDFD"
          Margin="0,0,0,0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0"
                   Margin="8,8,0,0"
                   TextWrapping="Wrap"
                   Text="{Binding Path=LeftHeader, RelativeSource={RelativeSource AncestorType=UserControl}}"
                   VerticalAlignment="Top" />
        <ListBox x:Name="LeftItemsList"
                 Grid.Column="0"
                 Margin="8,30,8,8"
                 MinWidth="150"
                 SelectionMode="Multiple"
                 ItemsSource="{Binding Path=LeftCollection}" />
        <StackPanel Grid.Column="1"
                    Margin="0"
                    Orientation="Vertical"
                    VerticalAlignment="Center">
            <Button Content="&gt;"
                    Height="25"
                    Width="25"
                    Click="Button_Click" />
            <Button Content="&gt;&gt;"
                    Height="25"
                    Width="25"
                    Click="Button_Click" />
            <Button Content="&lt;"
                    Height="25"
                    Width="25"
                    Click="Button_Click" />
            <Button Content="&lt;&lt;"
                    Height="25"
                    Width="25"
                    Click="Button_Click" />
        </StackPanel>
        <TextBlock Grid.Column="2"
                   Margin="8,8,8,0"
                   TextWrapping="Wrap"
                   Text="{Binding Path=RightHeader, RelativeSource={RelativeSource AncestorType=UserControl}}"
                   VerticalAlignment="Top" />
        <ListBox x:Name="RightItemsList"
                 Grid.Column="2"
                 Margin="8,30,8,8"
                 MinWidth="150"
                 SelectionMode="Multiple"
                 ItemsSource="{Binding Path=RightCollection}" />
    </Grid>
</Grid>
</UserControl>
public partial class ItemsSelectionLists : UserControl
 {
    #region properties
    public string LeftHeader
    {
        get
        {
            return (string) GetValue(LeftHeaderProperty);
        }
        set
        {
            SetValue(LeftHeaderProperty, value);
        }
    }
    // Using a DependencyProperty as the backing store for LeftHeader.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty LeftHeaderProperty =
        DependencyProperty.Register("LeftHeader", typeof(string), typeof(ItemsSelectionLists), new UIPropertyMetadata("Left List Header"));

    public string RightHeader
    {
        get
        {
            return (string) GetValue(RightHeaderProperty);
        }
        set
        {
            SetValue(RightHeaderProperty, value);
        }
    }

    // Using a DependencyProperty as the backing store for RightHeader.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty RightHeaderProperty =
        DependencyProperty.Register("RightHeader", typeof(string), typeof(ItemsSelectionLists), new UIPropertyMetadata("Right List Header"));

    private object dataSource;
    public object DataSource
    {
        get
        {
            return dataSource;
        }
        set
        {
            if (!value.GetType().FullName.StartsWith("TimeTracker.ViewModel"))
                throw new ArgumentException("DataSource is not an instance of ViewModel");
            if (dataSource != value)
            {
                dataSource = value;
                this.DataContext = this.DataSource;
                DataTemplateSelector templateSelector = dataSource as DataTemplateSelector;
                this.LeftItemsList.ItemTemplateSelector = templateSelector;
                this.RightItemsList.ItemTemplateSelector = templateSelector;
            }
        }
    }

    #endregion

    public ItemsSelectionLists()
        : base()
    {
        this.InitializeComponent();

    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var button = sender as Button;
        var type = dataSource.GetType();
        var MoveItems = type.GetMethod("MoveItems");
        var MoveAllItems = type.GetMethod("MoveAllItems");
        switch (button.Content.ToString())
        {
            case ">":
            MoveItems.Invoke(dataSource, new object[] { LeftItemsList, true });
            break;
            case ">>":
            MoveAllItems.Invoke(dataSource, new object[] { true });
            break;
            case "<":
            MoveItems.Invoke(dataSource, new object[] { RightItemsList, false });
            break;
            case "<<":
            MoveAllItems.Invoke(dataSource, new object[] { false });
            break;
        }
    }
}
public class ViewModel<T> : DataTemplateSelector, INotifyPropertyChanged
{
    #region Properties

    //this is just a placeholder for the collection, no changes will be made to this collection
    private ObservableCollection<T> leftCollectionRef;
    //local collection
    private ObservableCollection<T> leftCollection;
    public ObservableCollection<T> LeftCollection
    {
        get
        {
            return leftCollection;
        }

        set
        {
            if (value != leftCollectionRef)
            {
                //remove subscription to previous collection
                if (leftCollectionRef != null)
                    leftCollectionRef.CollectionChanged -= new NotifyCollectionChangedEventHandler(Ref_CollectionChanged);
                leftCollectionRef = value;
                leftCollection.Clear();
                foreach (var item in leftCollectionRef)
                {
                    if (rightCollection.IndexOf(item) == -1)
                        leftCollection.Add(item);
                }

                NotifyPropertyChanged("LeftCollection");
                //subscribe to chnages in new collection
                leftCollectionRef.CollectionChanged += new NotifyCollectionChangedEventHandler(Ref_CollectionChanged);
            }
        }
    }


    //this is just a placeholder for the collection, no changes will be made to this collection
    private ObservableCollection<T> rightCollectionRef;
    private ObservableCollection<T> rightCollection;
    public ObservableCollection<T> RightCollection
    {
        get
        {
            return rightCollection;
        }

        set
        {
            if (value != rightCollectionRef)
            {
                //remove subscription to previous collection
                if (rightCollectionRef != null)
                    rightCollectionRef.CollectionChanged -= new NotifyCollectionChangedEventHandler(Ref_CollectionChanged);
                rightCollectionRef = value;
                rightCollection.Clear();
                foreach (var item in rightCollectionRef)
                {
                    if (leftCollection.IndexOf(item) == -1)
                        rightCollection.Add(item);
                }

                NotifyPropertyChanged("RightCollection");
                rightCollectionRef.CollectionChanged += new NotifyCollectionChangedEventHandler(Ref_CollectionChanged);
            }
        }
    }

    private string bindingMember;
    public string BindingMember
    {
        get
        {
            return bindingMember;
        }
        set
        {
            var mem = typeof(T).GetProperty(value);
            if (mem == null)
                throw new ArgumentException("No Member " + value + " found in " + this.GetType().FullName);
            if (bindingMember != value)
            {
                bindingMember = value;
                NotifyPropertyChanged("BindingMember");
            }
        }
    }

    #endregion
    #region Constructors

    public ViewModel()
        : base()
    {
        // internal collection, this will get items copied over from reference source collection
        leftCollection = new ObservableCollection<T>();
        // internal collection, this will get items copied over from reference target collection
        rightCollection = new ObservableCollection<T>();
        bindingMember = "";
    }

    #endregion
    #region Movements
    public void MoveItems(ListBox list, bool LeftToRight)
    {
        var source = leftCollection;
        var target = rightCollection;
        if (!LeftToRight)
        {
            target = leftCollection;
            source = rightCollection;
        }

        if (list.SelectedItems.Count > 0)
        {
            // List for items to be removed.
            var hitList = new List<T>();

            // Move items
            foreach (T item in list.SelectedItems)
            {
                if (item != null)
                {
                    // Tag item for removal
                    hitList.Add(item);
                    // Check if item is in target list
                    if (target.IndexOf(item) == -1)
                    {
                        target.Add(item);
                    }
                }
            }

            // Remove items
            foreach (var hitItem in hitList)
            {
                source.Remove(hitItem);
            }
        }

    }
    public void MoveAllItems(bool LeftToRight)
    {
        if (LeftToRight)
        {
            rightCollection.Clear();
            foreach (var item in leftCollection)
            {
                RightCollection.Add(item);
            }
            leftCollection.Clear();
        }
        else
        {
            leftCollection.Clear();
            foreach (var item in rightCollection)
            {
                leftCollection.Add(item);
            }
            rightCollection.Clear();
        }
    }

    #endregion
    #region collection-monitor
    private void Ref_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null && e.NewItems.Count > 0)
        {
            var target = leftCollection;
            if (sender == leftCollectionRef)
                target = leftCollection;
            else
                target = rightCollection;

            foreach (T item in e.NewItems)
            {
                target.Add(item);
            }
        }

        //try remove from both collections, since the item may have moved to right or left collections
        if (e.OldItems != null && e.OldItems.Count > 0)
        {
            foreach (T item in e.OldItems)
            {
                leftCollection.Remove(item);
            }

            foreach (T item in e.OldItems)
            {
                rightCollection.Remove(item);
            }
        }
    }
    #endregion
    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    #endregion
    #region templateselector
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {

        string dataTemplate =
            @"<DataTemplate  
            xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">  
                <TextBlock Margin=""2"" TextWrapping=""Wrap"" Text=""{Binding Path=" + this.bindingMember + @", Mode=OneWay}""/>  
            </DataTemplate>";
        StringReader stringReader = new StringReader(dataTemplate);
        XmlReader xmlReader = XmlReader.Create(stringReader);
        return XamlReader.Load(xmlReader) as DataTemplate;
    }
    #endregion
}
<TabItem Header="Resource Allocation">
<local:ItemsSelectionLists x:Name="ProjectResourceMap" LeftHeader="Whole Team" RightHeader="Current Project Team"/>
</TabItem>
<TabItem Header="Tasks for the Project">
<local:ItemsSelectionLists x:Name="ProjectTaskMap" Margin="0" d:LayoutOverrides="Width" LeftHeader="All Tasks" RightHeader="Current Project Tasks"/>
</TabItem>

ViewModel<Resource> ProjectResource = new ViewModel<Resource>();
ProjectResource.BindingMember = "ResourceName";
this.ProjectResourceMap.DataSource = ProjectResource;
ProjectResource.LeftCollection = timeTracker.Resources;

ViewModel<Task> ProjectTasks = new ViewModel<Task>();
ProjectTasks.BindingMember = "TaskName";
this.ProjectTaskMap.DataSource = ProjectTasks;
ProjectTasks.LeftCollection = timeTracker.Tasks;