All the controls missing in WPF. Over 1 million downloads.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
8.2 KiB

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.Collections;
using System.Reflection;
namespace Microsoft.Windows.Controls
{
public class CollectionEditor : Control
{
#region Properties
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<object>), typeof(CollectionEditor), new UIPropertyMetadata(null));
public ObservableCollection<object> Items
{
get { return (ObservableCollection<object>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IList), typeof(CollectionEditor), new UIPropertyMetadata(null, OnItemsSourceChanged));
public IList ItemsSource
{
get { return (IList)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CollectionEditor collectionEditor = (CollectionEditor)d;
if (collectionEditor != null)
collectionEditor.OnItemSourceChanged((IList)e.OldValue, (IList)e.NewValue);
}
public void OnItemSourceChanged(IList oldValue, IList newValue)
{
if (newValue != null)
{
foreach (var item in newValue)
Items.Add(CreateClone(item));
}
}
public static readonly DependencyProperty ItemsSourceTypeProperty = DependencyProperty.Register("ItemsSourceType", typeof(Type), typeof(CollectionEditor), new UIPropertyMetadata(null, new PropertyChangedCallback(ItemsSourceTypeChanged)));
public Type ItemsSourceType
{
get { return (Type)GetValue(ItemsSourceTypeProperty); }
set { SetValue(ItemsSourceTypeProperty, value); }
}
private static void ItemsSourceTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CollectionEditor collectionEditor = (CollectionEditor)d;
if (collectionEditor != null)
collectionEditor.ItemsSourceTypeChanged((Type)e.OldValue, (Type)e.NewValue);
}
protected virtual void ItemsSourceTypeChanged(Type oldValue, Type newValue)
{
NewItemTypes = GetNewItemTypes(newValue);
}
public static readonly DependencyProperty NewItemTypesProperty = DependencyProperty.Register("NewItemTypes", typeof(IList), typeof(CollectionEditor), new UIPropertyMetadata(null));
public IList<Type> NewItemTypes
{
get { return (IList<Type>)GetValue(NewItemTypesProperty); }
set { SetValue(NewItemTypesProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(CollectionEditor), new UIPropertyMetadata(null));
public object SelectedItem
{
get { return (object)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
#endregion //Properties
#region Constructors
static CollectionEditor()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CollectionEditor), new FrameworkPropertyMetadata(typeof(CollectionEditor)));
}
public CollectionEditor()
{
Items = new ObservableCollection<object>();
CommandBindings.Add(new CommandBinding(ApplicationCommands.New, AddNew, CanAddNew));
CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete, Delete, CanDelete));
CommandBindings.Add(new CommandBinding(ComponentCommands.MoveDown, MoveDown, CanMoveDown));
CommandBindings.Add(new CommandBinding(ComponentCommands.MoveUp, MoveUp, CanMoveUp));
}
#endregion //Constructors
#region Commands
private void AddNew(object sender, ExecutedRoutedEventArgs e)
{
var newItem = CreateNewItem((Type)e.Parameter);
Items.Add(newItem);
SelectedItem = newItem;
}
private void CanAddNew(object sender, CanExecuteRoutedEventArgs e)
{
Type t = e.Parameter as Type;
if (t != null && t.GetConstructor(Type.EmptyTypes) != null)
e.CanExecute = true;
}
private void Delete(object sender, ExecutedRoutedEventArgs e)
{
Items.Remove(e.Parameter);
}
private void CanDelete(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
}
private void MoveDown(object sender, ExecutedRoutedEventArgs e)
{
var selectedItem = e.Parameter;
var index = Items.IndexOf(selectedItem);
Items.RemoveAt(index);
Items.Insert(++index, selectedItem);
SelectedItem = selectedItem;
}
private void CanMoveDown(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Parameter != null && Items.IndexOf(e.Parameter) < (Items.Count - 1))
e.CanExecute = true;
}
private void MoveUp(object sender, ExecutedRoutedEventArgs e)
{
var selectedItem = e.Parameter;
var index = Items.IndexOf(selectedItem);
Items.RemoveAt(index);
Items.Insert(--index, selectedItem);
SelectedItem = selectedItem;
}
private void CanMoveUp(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Parameter != null && Items.IndexOf(e.Parameter) > 0)
e.CanExecute = true;
}
#endregion //Commands
#region Methods
private static void CopyValues(object source, object destination)
{
FieldInfo[] myObjectFields = source.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo fi in myObjectFields)
{
fi.SetValue(destination, fi.GetValue(source));
}
}
private object CreateClone(object source)
{
object clone = null;
Type type = source.GetType();
clone = Activator.CreateInstance(type);
CopyValues(source, clone);
return clone;
}
private IList CreateItemsSource()
{
IList list = null;
if (ItemsSourceType != null)
{
ConstructorInfo constructor = ItemsSourceType.GetConstructor(Type.EmptyTypes);
list = (IList)constructor.Invoke(null);
}
return list;
}
private object CreateNewItem(Type type)
{
return Activator.CreateInstance(type);
}
private static List<Type> GetNewItemTypes(Type type)
{
List<Type> types = new List<Type>();
var newItemTypes = type.GetGenericArguments();
foreach (var t in newItemTypes)
{
types.Add(t);
}
return types;
}
public void PersistChanges()
{
IList list = ResolveItemsSource();
if (list == null)
return;
//the easiest way to persist changes to the source is to just clear the source list and then add all items to it.
list.Clear();
foreach (var item in Items)
{
list.Add(item);
}
}
private IList ResolveItemsSource()
{
if (ItemsSource == null)
ItemsSource = CreateItemsSource();
return ItemsSource;
}
#endregion //Methods
}
}