|
|
@ -1,72 +1,75 @@ |
|
|
using System; |
|
|
using System; |
|
|
using System.Collections.Generic; |
|
|
using System.Collections.Generic; |
|
|
using System.Linq; |
|
|
|
|
|
using System.Text; |
|
|
|
|
|
using System.Windows; |
|
|
using System.Windows; |
|
|
using System.Windows.Controls; |
|
|
using System.Windows.Controls; |
|
|
using System.Windows.Data; |
|
|
|
|
|
using System.Windows.Documents; |
|
|
|
|
|
using System.Windows.Input; |
|
|
using System.Windows.Input; |
|
|
using System.Windows.Media; |
|
|
|
|
|
using System.Windows.Media.Imaging; |
|
|
|
|
|
using System.Windows.Shapes; |
|
|
|
|
|
using System.Collections; |
|
|
|
|
|
using System.Collections.ObjectModel; |
|
|
using System.Collections.ObjectModel; |
|
|
|
|
|
using System.Collections; |
|
|
using System.Reflection; |
|
|
using System.Reflection; |
|
|
using System.ComponentModel; |
|
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.Windows.Controls.PropertyGrid.Editors |
|
|
namespace Microsoft.Windows.Controls |
|
|
{ |
|
|
{ |
|
|
/// <summary>
|
|
|
public class CollectionEditor : Control |
|
|
/// Interaction logic for CollectionEditorDialog.xaml
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public partial class CollectionEditorDialog : Window |
|
|
|
|
|
{ |
|
|
{ |
|
|
#region Properties
|
|
|
#region Properties
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<object>), typeof(CollectionEditorDialog), new UIPropertyMetadata(null)); |
|
|
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<object>), typeof(CollectionEditor), new UIPropertyMetadata(null)); |
|
|
public ObservableCollection<object> Items |
|
|
public ObservableCollection<object> Items |
|
|
{ |
|
|
{ |
|
|
get { return (ObservableCollection<object>)GetValue(ItemsProperty); } |
|
|
get { return (ObservableCollection<object>)GetValue(ItemsProperty); } |
|
|
set { SetValue(ItemsProperty, value); } |
|
|
set { SetValue(ItemsProperty, value); } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CollectionEditorDialog), new UIPropertyMetadata(null, OnItemsSourceChanged)); |
|
|
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IList), typeof(CollectionEditor), new UIPropertyMetadata(null, OnItemsSourceChanged)); |
|
|
public IEnumerable ItemsSource |
|
|
public IList ItemsSource |
|
|
{ |
|
|
{ |
|
|
get { return (IEnumerable)GetValue(ItemsSourceProperty); } |
|
|
get { return (IList)GetValue(ItemsSourceProperty); } |
|
|
set { SetValue(ItemsSourceProperty, value); } |
|
|
set { SetValue(ItemsSourceProperty, value); } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
{ |
|
|
{ |
|
|
CollectionEditorDialog collectionEditor = (CollectionEditorDialog)d; |
|
|
CollectionEditor collectionEditor = (CollectionEditor)d; |
|
|
if (collectionEditor != null) |
|
|
if (collectionEditor != null) |
|
|
collectionEditor.OnItemSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue); |
|
|
collectionEditor.OnItemSourceChanged((IList)e.OldValue, (IList)e.NewValue); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void OnItemSourceChanged(IEnumerable oldValue, IEnumerable newValue) |
|
|
public void OnItemSourceChanged(IList oldValue, IList newValue) |
|
|
{ |
|
|
{ |
|
|
if (newValue != null) |
|
|
if (newValue != null) |
|
|
{ |
|
|
{ |
|
|
Items = new ObservableCollection<object>(); |
|
|
|
|
|
foreach (var item in newValue) |
|
|
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 |
|
|
{ |
|
|
{ |
|
|
object clone = Activator.CreateInstance(item.GetType()); |
|
|
get { return (Type)GetValue(ItemsSourceTypeProperty); } |
|
|
CopyValues(item, clone); |
|
|
set { SetValue(ItemsSourceTypeProperty, value); } |
|
|
Items.Add(clone); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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(CollectionEditorDialog), new UIPropertyMetadata(null)); |
|
|
public static readonly DependencyProperty NewItemTypesProperty = DependencyProperty.Register("NewItemTypes", typeof(IList), typeof(CollectionEditor), new UIPropertyMetadata(null)); |
|
|
public IList<Type> NewItemTypes |
|
|
public IList<Type> NewItemTypes |
|
|
{ |
|
|
{ |
|
|
get { return (IList<Type>)GetValue(NewItemTypesProperty); } |
|
|
get { return (IList<Type>)GetValue(NewItemTypesProperty); } |
|
|
set { SetValue(NewItemTypesProperty, value); } |
|
|
set { SetValue(NewItemTypesProperty, value); } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(CollectionEditorDialog), new UIPropertyMetadata(null)); |
|
|
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(CollectionEditor), new UIPropertyMetadata(null)); |
|
|
public object SelectedItem |
|
|
public object SelectedItem |
|
|
{ |
|
|
{ |
|
|
get { return (object)GetValue(SelectedItemProperty); } |
|
|
get { return (object)GetValue(SelectedItemProperty); } |
|
|
@ -77,61 +80,27 @@ namespace Microsoft.Windows.Controls.PropertyGrid.Editors |
|
|
|
|
|
|
|
|
#region Constructors
|
|
|
#region Constructors
|
|
|
|
|
|
|
|
|
private CollectionEditorDialog() |
|
|
static CollectionEditor() |
|
|
{ |
|
|
{ |
|
|
InitializeComponent(); |
|
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(CollectionEditor), new FrameworkPropertyMetadata(typeof(CollectionEditor))); |
|
|
DataContext = this; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public CollectionEditorDialog(Type type) |
|
|
public CollectionEditor() |
|
|
: this() |
|
|
|
|
|
{ |
|
|
{ |
|
|
NewItemTypes = GetNewItemTypes(type); |
|
|
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
|
|
|
#endregion //Constructors
|
|
|
|
|
|
|
|
|
private void OkButton_Click(object sender, RoutedEventArgs e) |
|
|
|
|
|
{ |
|
|
|
|
|
PersistChanges(); |
|
|
|
|
|
Close(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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 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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void PersistChanges() |
|
|
|
|
|
{ |
|
|
|
|
|
if (ItemsSource is IList) |
|
|
|
|
|
{ |
|
|
|
|
|
IList list = (IList)ItemsSource; |
|
|
|
|
|
//Need to copy all changes into ItemsSource
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#region Commands
|
|
|
#region Commands
|
|
|
|
|
|
|
|
|
private void AddNew(object sender, ExecutedRoutedEventArgs e) |
|
|
private void AddNew(object sender, ExecutedRoutedEventArgs e) |
|
|
{ |
|
|
{ |
|
|
Type t = (Type)e.Parameter; |
|
|
var newItem = CreateNewItem((Type)e.Parameter); |
|
|
var newItem = Activator.CreateInstance(t); |
|
|
|
|
|
Items.Add(newItem); |
|
|
Items.Add(newItem); |
|
|
SelectedItem = newItem; |
|
|
SelectedItem = newItem; |
|
|
} |
|
|
} |
|
|
@ -139,7 +108,7 @@ namespace Microsoft.Windows.Controls.PropertyGrid.Editors |
|
|
private void CanAddNew(object sender, CanExecuteRoutedEventArgs e) |
|
|
private void CanAddNew(object sender, CanExecuteRoutedEventArgs e) |
|
|
{ |
|
|
{ |
|
|
Type t = e.Parameter as Type; |
|
|
Type t = e.Parameter as Type; |
|
|
if (t != null && t.IsClass) |
|
|
if (t != null && t.GetConstructor(Type.EmptyTypes) != null) |
|
|
e.CanExecute = true; |
|
|
e.CanExecute = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -184,5 +153,81 @@ namespace Microsoft.Windows.Controls.PropertyGrid.Editors |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#endregion //Commands
|
|
|
#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
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |