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.
290 lines
8.7 KiB
290 lines
8.7 KiB
/************************************************************************
|
|
|
|
Extended WPF Toolkit
|
|
|
|
Copyright (C) 2010-2012 Xceed Software Inc.
|
|
|
|
This program is provided to you under the terms of the Microsoft Public
|
|
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
|
|
|
This program can be provided to you by Xceed Software Inc. under a
|
|
proprietary commercial license agreement for use in non-Open Source
|
|
projects. The commercial version of Extended WPF Toolkit also includes
|
|
priority technical support, commercial updates, and many additional
|
|
useful WPF controls if you license Xceed Business Suite for WPF.
|
|
|
|
Visit http://xceed.com and follow @datagrid on Twitter.
|
|
|
|
**********************************************************************/
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
|
|
namespace Xceed.Wpf.Toolkit
|
|
{
|
|
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 )
|
|
{
|
|
List<Type> types = new List<Type>();
|
|
Type listType = GetListItemType( newValue );
|
|
|
|
if( listType != null )
|
|
{
|
|
types.Add( listType );
|
|
}
|
|
|
|
NewItemTypes = types;
|
|
}
|
|
|
|
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 );
|
|
}
|
|
|
|
internal static Type GetListItemType(Type listType)
|
|
{
|
|
Type iListOfT = listType.GetInterfaces().FirstOrDefault(
|
|
( i ) => i.IsGenericType && i.GetGenericTypeDefinition() == typeof( IList<> ) );
|
|
|
|
return ( iListOfT != null )
|
|
? iListOfT.GetGenericArguments()[ 0 ]
|
|
: null;
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|