C# WPF中的数据绑定列表框子选择
好吧,我可能问了一个古老的问题,但我没有在任何一个问题中描述我的情景 我有一个可以包含多个子对象的项目。一个项目obejct可以有几个资源对象。我有一个ObservaleCollection,其中包含子OBEJCT的超集(在我的例子中是资源对象)。我在项目对象中还有另一个ObservableCollection,它包含现有的child 在WPF windows应用程序中向用户呈现此内容的最佳方式是什么?我还需要为他们提供一种方法来改变映射 我最初的想法是使用经典的双列表方法,使用两个列表框,但我不确定单独操作视图层有多容易C# WPF中的数据绑定列表框子选择,c#,wpf,user-controls,listbox,C#,Wpf,User Controls,Listbox,好吧,我可能问了一个古老的问题,但我没有在任何一个问题中描述我的情景 我有一个可以包含多个子对象的项目。一个项目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=">" Width="60" Click="MoveRightEvent" />
<Button Content=">>" Width="60" Click="MoveAllRightEvent" />
<Button Content="<<" Width="60" Click="MoveAllLeftEvent" />
<Button Content="<" 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=">"
Height="25"
Width="25"
Click="Button_Click" />
<Button Content=">>"
Height="25"
Width="25"
Click="Button_Click" />
<Button Content="<"
Height="25"
Width="25"
Click="Button_Click" />
<Button Content="<<"
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;