This commit is contained in:
2024-02-23 07:03:56 -05:00
commit 4a3813687a
937 changed files with 113251 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

View File

@@ -0,0 +1,598 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit
{
[TemplatePart( Name = PART_NewItemTypesComboBox, Type = typeof( ComboBox ) )]
[TemplatePart( Name = PART_PropertyGrid, Type = typeof( PropertyGrid.PropertyGrid ) )]
[TemplatePart( Name = PART_ListBox, Type = typeof( ListBox ) )]
public class CollectionControl : Control
{
private const string PART_NewItemTypesComboBox = "PART_NewItemTypesComboBox";
private const string PART_PropertyGrid = "PART_PropertyGrid";
private const string PART_ListBox = "PART_ListBox";
#region Private Members
private ComboBox _newItemTypesComboBox;
private PropertyGrid.PropertyGrid _propertyGrid;
private ListBox _listBox;
#endregion
#region Properties
#region IsReadOnly Property
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( CollectionControl ), new UIPropertyMetadata( false ) );
public bool IsReadOnly
{
get
{
return ( bool )GetValue( IsReadOnlyProperty );
}
set
{
SetValue( IsReadOnlyProperty, value );
}
}
#endregion //Items
#region Items Property
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register( "Items", typeof( ObservableCollection<object> ), typeof( CollectionControl ), new UIPropertyMetadata( null ) );
public ObservableCollection<object> Items
{
get
{
return ( ObservableCollection<object> )GetValue( ItemsProperty );
}
set
{
SetValue( ItemsProperty, value );
}
}
#endregion //Items
#region ItemsSource Property
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( "ItemsSource", typeof( IEnumerable ), typeof( CollectionControl ), new UIPropertyMetadata( null, OnItemsSourceChanged ) );
public IEnumerable ItemsSource
{
get
{
return (IEnumerable)GetValue( ItemsSourceProperty );
}
set
{
SetValue( ItemsSourceProperty, value );
}
}
private static void OnItemsSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
var CollectionControl = ( CollectionControl )d;
if( CollectionControl != null )
CollectionControl.OnItemSourceChanged( (IEnumerable)e.OldValue, (IEnumerable)e.NewValue );
}
public void OnItemSourceChanged( IEnumerable oldValue, IEnumerable newValue )
{
if( newValue != null )
{
var dict = newValue as IDictionary;
if( dict != null )
{
// A Dictionary contains KeyValuePair that can't be edited.
// We need to Add EditableKeyValuePairs from DictionaryEntries.
foreach( DictionaryEntry item in dict )
{
var keyType = (item.Key != null)
? item.Key.GetType()
: (dict.GetType().GetGenericArguments().Count() > 0) ? dict.GetType().GetGenericArguments()[0] : typeof( object );
var valueType = (item.Value != null)
? item.Value.GetType()
: (dict.GetType().GetGenericArguments().Count() > 1) ? dict.GetType().GetGenericArguments()[ 1 ] : typeof( object );
var editableKeyValuePair = ListUtilities.CreateEditableKeyValuePair( item.Key
, keyType
, item.Value
, valueType );
this.Items.Add( editableKeyValuePair );
}
}
else
{
foreach( var item in newValue )
{
if( item != null )
{
Items.Add( item );
}
}
}
}
}
#endregion //ItemsSource
#region ItemsSourceType Property
public static readonly DependencyProperty ItemsSourceTypeProperty = DependencyProperty.Register( "ItemsSourceType", typeof( Type ), typeof( CollectionControl ), new UIPropertyMetadata( null ) );
public Type ItemsSourceType
{
get
{
return ( Type )GetValue( ItemsSourceTypeProperty );
}
set
{
SetValue( ItemsSourceTypeProperty, value );
}
}
#endregion //ItemsSourceType
#region NewItemType Property
public static readonly DependencyProperty NewItemTypesProperty = DependencyProperty.Register( "NewItemTypes", typeof( IList ), typeof( CollectionControl ), new UIPropertyMetadata( null ) );
public IList<Type> NewItemTypes
{
get
{
return ( IList<Type> )GetValue( NewItemTypesProperty );
}
set
{
SetValue( NewItemTypesProperty, value );
}
}
#endregion //NewItemType
#region SelectedItem Property
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( "SelectedItem", typeof( object ), typeof( CollectionControl ), new UIPropertyMetadata( null ) );
public object SelectedItem
{
get
{
return ( object )GetValue( SelectedItemProperty );
}
set
{
SetValue( SelectedItemProperty, value );
}
}
#endregion //SelectedItem
#endregion //Properties
#region Override Methods
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if( _newItemTypesComboBox != null )
{
_newItemTypesComboBox.Loaded -= new RoutedEventHandler( this.NewItemTypesComboBox_Loaded );
}
_newItemTypesComboBox = GetTemplateChild( PART_NewItemTypesComboBox ) as ComboBox;
if( _newItemTypesComboBox != null )
{
_newItemTypesComboBox.Loaded += new RoutedEventHandler( this.NewItemTypesComboBox_Loaded );
}
_listBox = this.GetTemplateChild( PART_ListBox ) as ListBox;
if( _propertyGrid != null )
{
_propertyGrid.PropertyValueChanged -= this.PropertyGrid_PropertyValueChanged;
}
_propertyGrid = GetTemplateChild( PART_PropertyGrid ) as PropertyGrid.PropertyGrid;
if( _propertyGrid != null )
{
_propertyGrid.PropertyValueChanged += this.PropertyGrid_PropertyValueChanged;
}
}
public PropertyGrid.PropertyGrid PropertyGrid
{
get
{
if( _propertyGrid == null )
{
this.ApplyTemplate();
}
return _propertyGrid;
}
}
#endregion
#region Constructors
static CollectionControl()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( CollectionControl ), new FrameworkPropertyMetadata( typeof( CollectionControl ) ) );
}
public CollectionControl()
{
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 Events
#region ItemDeleting Event
public delegate void ItemDeletingRoutedEventHandler( object sender, ItemDeletingEventArgs e );
public static readonly RoutedEvent ItemDeletingEvent = EventManager.RegisterRoutedEvent( "ItemDeleting", RoutingStrategy.Bubble, typeof( ItemDeletingRoutedEventHandler ), typeof( CollectionControl ) );
public event ItemDeletingRoutedEventHandler ItemDeleting
{
add
{
AddHandler( ItemDeletingEvent, value );
}
remove
{
RemoveHandler( ItemDeletingEvent, value );
}
}
#endregion //ItemDeleting Event
#region ItemDeleted Event
public delegate void ItemDeletedRoutedEventHandler( object sender, ItemEventArgs e );
public static readonly RoutedEvent ItemDeletedEvent = EventManager.RegisterRoutedEvent( "ItemDeleted", RoutingStrategy.Bubble, typeof( ItemDeletedRoutedEventHandler ), typeof( CollectionControl ) );
public event ItemDeletedRoutedEventHandler ItemDeleted
{
add
{
AddHandler( ItemDeletedEvent, value );
}
remove
{
RemoveHandler( ItemDeletedEvent, value );
}
}
#endregion //ItemDeleted Event
#region ItemAdding Event
public delegate void ItemAddingRoutedEventHandler( object sender, ItemAddingEventArgs e );
public static readonly RoutedEvent ItemAddingEvent = EventManager.RegisterRoutedEvent( "ItemAdding", RoutingStrategy.Bubble, typeof( ItemAddingRoutedEventHandler ), typeof( CollectionControl ) );
public event ItemAddingRoutedEventHandler ItemAdding
{
add
{
AddHandler( ItemAddingEvent, value );
}
remove
{
RemoveHandler( ItemAddingEvent, value );
}
}
#endregion //ItemAdding Event
#region ItemAdded Event
public delegate void ItemAddedRoutedEventHandler( object sender, ItemEventArgs e );
public static readonly RoutedEvent ItemAddedEvent = EventManager.RegisterRoutedEvent( "ItemAdded", RoutingStrategy.Bubble, typeof( ItemAddedRoutedEventHandler ), typeof( CollectionControl ) );
public event ItemAddedRoutedEventHandler ItemAdded
{
add
{
AddHandler( ItemAddedEvent, value );
}
remove
{
RemoveHandler( ItemAddedEvent, value );
}
}
#endregion //ItemAdded Event
#region ItemMovedDown Event
public delegate void ItemMovedDownRoutedEventHandler( object sender, ItemEventArgs e );
public static readonly RoutedEvent ItemMovedDownEvent = EventManager.RegisterRoutedEvent( "ItemMovedDown", RoutingStrategy.Bubble, typeof( ItemMovedDownRoutedEventHandler ), typeof( CollectionControl ) );
public event ItemMovedDownRoutedEventHandler ItemMovedDown
{
add
{
AddHandler( ItemMovedDownEvent, value );
}
remove
{
RemoveHandler( ItemMovedDownEvent, value );
}
}
#endregion //ItemMovedDown Event
#region ItemMovedUp Event
public delegate void ItemMovedUpRoutedEventHandler( object sender, ItemEventArgs e );
public static readonly RoutedEvent ItemMovedUpEvent = EventManager.RegisterRoutedEvent( "ItemMovedUp", RoutingStrategy.Bubble, typeof( ItemMovedUpRoutedEventHandler ), typeof( CollectionControl ) );
public event ItemMovedUpRoutedEventHandler ItemMovedUp
{
add
{
AddHandler( ItemMovedUpEvent, value );
}
remove
{
RemoveHandler( ItemMovedUpEvent, value );
}
}
#endregion //ItemMovedUp Event
#endregion
#region EventHandlers
void NewItemTypesComboBox_Loaded( object sender, RoutedEventArgs e )
{
if( _newItemTypesComboBox != null )
_newItemTypesComboBox.SelectedIndex = 0;
}
private void PropertyGrid_PropertyValueChanged( object sender, PropertyGrid.PropertyValueChangedEventArgs e )
{
if( _listBox != null )
{
_listBox.Items.Refresh();
}
}
#endregion
#region Commands
private void AddNew( object sender, ExecutedRoutedEventArgs e )
{
var newItem = CreateNewItem( ( Type )e.Parameter );
var properties = newItem.GetType().GetProperties();
foreach( var property in properties )
{
// For Generic Types, add an empty collection/list of T.
if( property.CanWrite && property.PropertyType.IsGenericType )
{
var genericCollection = Activator.CreateInstance( property.PropertyType );
property.SetValue( newItem, genericCollection, null );
}
}
var eventArgs = new ItemAddingEventArgs( ItemAddingEvent, newItem );
this.RaiseEvent( eventArgs );
if( eventArgs.Cancel )
return;
newItem = eventArgs.Item;
Items.Add( newItem );
this.RaiseEvent( new ItemEventArgs( ItemAddedEvent, newItem ) );
SelectedItem = newItem;
}
private void CanAddNew( object sender, CanExecuteRoutedEventArgs e )
{
Type t = e.Parameter as Type;
if( (t != null) && !this.IsReadOnly )
{
bool isComplexStruct = t.IsValueType && !t.IsEnum && !t.IsPrimitive;
if( isComplexStruct || (t.GetConstructor( Type.EmptyTypes ) != null) )
{
e.CanExecute = true;
}
}
}
private void Delete( object sender, ExecutedRoutedEventArgs e )
{
var eventArgs = new ItemDeletingEventArgs( ItemDeletingEvent, e.Parameter );
this.RaiseEvent( eventArgs );
if( eventArgs.Cancel )
return;
Items.Remove( e.Parameter );
this.RaiseEvent( new ItemEventArgs( ItemDeletedEvent, e.Parameter ) );
}
private void CanDelete( object sender, CanExecuteRoutedEventArgs e )
{
e.CanExecute = e.Parameter != null && !IsReadOnly;
}
private void MoveDown( object sender, ExecutedRoutedEventArgs e )
{
var selectedItem = e.Parameter;
var index = Items.IndexOf( selectedItem );
Items.RemoveAt( index );
Items.Insert( ++index, selectedItem );
this.RaiseEvent( new ItemEventArgs( ItemMovedDownEvent, selectedItem ) );
SelectedItem = selectedItem;
}
private void CanMoveDown( object sender, CanExecuteRoutedEventArgs e )
{
if( e.Parameter != null && Items.IndexOf( e.Parameter ) < ( Items.Count - 1 ) && !IsReadOnly )
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 );
this.RaiseEvent( new ItemEventArgs( ItemMovedUpEvent, selectedItem ) );
SelectedItem = selectedItem;
}
private void CanMoveUp( object sender, CanExecuteRoutedEventArgs e )
{
if( e.Parameter != null && Items.IndexOf( e.Parameter ) > 0 && !IsReadOnly )
e.CanExecute = true;
}
#endregion //Commands
#region Methods
public void PersistChanges()
{
this.PersistChanges( this.Items );
}
internal void PersistChanges( IList sourceList )
{
var collection = ComputeItemsSource();
if( collection == null )
return;
//IDictionary<T> and IDictionary
if( collection is IDictionary )
{
//For a Dictionary, we need to parse the list of EditableKeyValuePair and add KeyValuePair to the Dictionary.
var dict = (IDictionary)collection;
//the easiest way to persist changes to the source is to just clear the source list and then add all items to it.
dict.Clear();
foreach( var item in sourceList )
{
var propInfoKey = item.GetType().GetProperty( "Key" );
var propInfoValue = item.GetType().GetProperty( "Value" );
if( (propInfoKey != null) && (propInfoValue != null) )
{
dict.Add( propInfoKey.GetValue( item, null ), propInfoValue.GetValue( item, null ) );
}
}
}
//IList
else if( collection is IList )
{
var list = (IList)collection;
//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();
if( list.IsFixedSize )
{
for( int i = 0; i < sourceList.Count; ++i )
list[ i ] = sourceList[ i ];
}
else
{
foreach( var item in sourceList )
{
list.Add( item );
}
}
}
else
{
//ICollection<T> (or IList<T>)
var collectionType = collection.GetType();
var iCollectionOfTInterface = collectionType.GetInterfaces().FirstOrDefault( x => x.IsGenericType && (x.GetGenericTypeDefinition() == typeof( ICollection<> )) );
if( iCollectionOfTInterface != null )
{
var argumentType = iCollectionOfTInterface.GetGenericArguments().FirstOrDefault();
if( argumentType != null )
{
var iCollectionOfTType = typeof( ICollection<> ).MakeGenericType( argumentType );
//the easiest way to persist changes to the source is to just clear the source list and then add all items to it.
iCollectionOfTType.GetMethod( "Clear" ).Invoke( collection, null );
foreach( var item in sourceList )
{
iCollectionOfTType.GetMethod( "Add" ).Invoke( collection, new object[] { item } );
}
}
}
}
}
private IEnumerable CreateItemsSource()
{
IEnumerable collection = null;
if( ItemsSourceType != null )
{
var constructor = ItemsSourceType.GetConstructor( Type.EmptyTypes );
if( constructor != null )
{
collection = (IEnumerable)constructor.Invoke( null );
}
}
return collection;
}
private object CreateNewItem( Type type )
{
return Activator.CreateInstance( type );
}
private IEnumerable ComputeItemsSource()
{
if( ItemsSource == null )
ItemsSource = CreateItemsSource();
return ItemsSource;
}
#endregion //Methods
}
}

View File

@@ -0,0 +1,127 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace Xceed.Wpf.Toolkit
{
public class CollectionControlButton : Button
{
#region Constructors
static CollectionControlButton()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( CollectionControlButton ), new FrameworkPropertyMetadata( typeof( CollectionControlButton ) ) );
}
public CollectionControlButton()
{
this.Click += this.CollectionControlButton_Click;
}
#endregion //Constructors
#region Properties
#region IsReadOnly Property
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( CollectionControlButton ), new UIPropertyMetadata( false ) );
public bool IsReadOnly
{
get
{
return ( bool )GetValue( IsReadOnlyProperty );
}
set
{
SetValue( IsReadOnlyProperty, value );
}
}
#endregion //IsReadOnly
#region ItemsSource Property
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( "ItemsSource", typeof( IEnumerable ), typeof( CollectionControlButton ), new UIPropertyMetadata( null ) );
public IEnumerable ItemsSource
{
get
{
return (IEnumerable)GetValue( ItemsSourceProperty );
}
set
{
SetValue( ItemsSourceProperty, value );
}
}
#endregion //ItemsSource
#region ItemsSourceType Property
public static readonly DependencyProperty ItemsSourceTypeProperty = DependencyProperty.Register( "ItemsSourceType", typeof( Type ), typeof( CollectionControlButton ), new UIPropertyMetadata( null ) );
public Type ItemsSourceType
{
get
{
return ( Type )GetValue( ItemsSourceTypeProperty );
}
set
{
SetValue( ItemsSourceTypeProperty, value );
}
}
#endregion //ItemsSourceType
#region NewItemTypes Property
public static readonly DependencyProperty NewItemTypesProperty = DependencyProperty.Register( "NewItemTypes", typeof( IList ), typeof( CollectionControlButton ), new UIPropertyMetadata( null ) );
public IList<Type> NewItemTypes
{
get
{
return ( IList<Type> )GetValue( NewItemTypesProperty );
}
set
{
SetValue( NewItemTypesProperty, value );
}
}
#endregion //NewItemTypes
#endregion
#region Methods
private void CollectionControlButton_Click( object sender, RoutedEventArgs e )
{
var collectionControlDialog = new CollectionControlDialog();
collectionControlDialog.ItemsSource = this.ItemsSource;
collectionControlDialog.NewItemTypes = this.NewItemTypes;
collectionControlDialog.ItemsSourceType = this.ItemsSourceType;
collectionControlDialog.IsReadOnly = this.IsReadOnly;
collectionControlDialog.ShowDialog();
}
#endregion
}
}

View File

@@ -0,0 +1,53 @@
<!--***********************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
**********************************************************************************-->
<local:CollectionControlDialogBase x:Class="Xceed.Wpf.Toolkit.CollectionControlDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xceed.Wpf.Toolkit"
Title="Collection Control"
Height="400"
Width="600"
WindowStartupLocation="CenterScreen">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:CollectionControl x:Name="_collectionControl"
ItemsSourceType="{Binding ItemsSourceType, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Mode=TwoWay}"
NewItemTypes="{Binding NewItemTypes, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
<StackPanel Orientation="Horizontal"
Grid.Row="1"
HorizontalAlignment="Right"
Margin="5">
<Button Width="75"
Margin="2"
Click="OkButton_Click"
IsDefault="True">OK</Button>
<Button Width="75"
Margin="2"
Click="CancelButton_Click"
IsCancel="True">Cancel</Button>
</StackPanel>
</Grid>
</local:CollectionControlDialogBase>

View File

@@ -0,0 +1,302 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using Xceed.Wpf.Toolkit.Core.Utilities;
using System.Linq;
using System.Runtime.Serialization;
using System.Security;
namespace Xceed.Wpf.Toolkit
{
public partial class CollectionControlDialogBase :
Window
{
}
/// <summary>
/// Interaction logic for CollectionControlDialog.xaml
/// </summary>
public partial class CollectionControlDialog : CollectionControlDialogBase
{
#region Private Members
private IList originalData = new List<object>();
#endregion
#region Properties
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( "ItemsSource", typeof( IEnumerable ), typeof( CollectionControlDialog ), new UIPropertyMetadata( null ) );
public IEnumerable ItemsSource
{
get
{
return (IEnumerable)GetValue( ItemsSourceProperty );
}
set
{
SetValue( ItemsSourceProperty, value );
}
}
public static readonly DependencyProperty ItemsSourceTypeProperty = DependencyProperty.Register( "ItemsSourceType", typeof( Type ), typeof( CollectionControlDialog ), new UIPropertyMetadata( null ) );
public Type ItemsSourceType
{
get
{
return ( Type )GetValue( ItemsSourceTypeProperty );
}
set
{
SetValue( ItemsSourceTypeProperty, value );
}
}
public static readonly DependencyProperty NewItemTypesProperty = DependencyProperty.Register( "NewItemTypes", typeof( IList ), typeof( CollectionControlDialog ), new UIPropertyMetadata( null ) );
public IList<Type> NewItemTypes
{
get
{
return ( IList<Type> )GetValue( NewItemTypesProperty );
}
set
{
SetValue( NewItemTypesProperty, value );
}
}
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( CollectionControlDialog ), new UIPropertyMetadata( false ) );
public bool IsReadOnly
{
get
{
return ( bool )GetValue( IsReadOnlyProperty );
}
set
{
SetValue( IsReadOnlyProperty, value );
}
}
public CollectionControl CollectionControl
{
get
{
return _collectionControl;
}
}
#endregion //Properties
#region Constructors
public CollectionControlDialog()
{
InitializeComponent();
}
public CollectionControlDialog( Type itemsourceType )
: this()
{
ItemsSourceType = itemsourceType;
}
public CollectionControlDialog( Type itemsourceType, IList<Type> newItemTypes )
: this( itemsourceType )
{
NewItemTypes = newItemTypes;
}
#endregion //Constructors
#region Overrides
protected override void OnSourceInitialized( EventArgs e )
{
base.OnSourceInitialized( e );
//Backup data in case "Cancel" is clicked.
if( this.ItemsSource != null )
{
foreach( var item in this.ItemsSource )
{
originalData.Add( this.Clone( item ) );
}
}
}
#endregion
#region Event Handlers
private void OkButton_Click( object sender, RoutedEventArgs e )
{
if( this.ItemsSource is IDictionary )
{
if( !this.AreDictionaryKeysValid() )
{
MessageBox.Show( "All dictionary items should have distinct non-null Key values.", "Warning" );
return;
}
}
_collectionControl.PersistChanges();
this.DialogResult = true;
this.Close();
}
private void CancelButton_Click( object sender, RoutedEventArgs e )
{
_collectionControl.PersistChanges( originalData );
this.DialogResult = false;
this.Close();
}
#endregion //Event Hanlders
#region Private Methods
[SecuritySafeCritical]
private object Clone( object source )
{
if( source == null )
return null;
object result = null;
var sourceType = source.GetType();
// For IDictionary, we need to create EditableKeyValuePair to edit the Key-Value.
if( (this.ItemsSource is IDictionary)
&& sourceType.IsGenericType
&& typeof( KeyValuePair<,> ).IsAssignableFrom( sourceType.GetGenericTypeDefinition() ) )
{
result = this.GenerateEditableKeyValuePair( source );
}
else
{
// Initialized a new object with default values
result = FormatterServices.GetUninitializedObject( sourceType );
var constructor = sourceType.GetConstructor( Type.EmptyTypes );
if( constructor == null )
return null;
constructor.Invoke( result, null );
}
Debug.Assert( result != null );
if( result != null )
{
var properties = sourceType.GetProperties();
foreach( var propertyInfo in properties )
{
var parameters = propertyInfo.GetIndexParameters();
var index = parameters.GetLength( 0 ) == 0 ? null : new object[] { parameters.GetLength( 0 ) - 1 };
var propertyInfoValue = propertyInfo.GetValue( source, index );
if( propertyInfo.CanWrite )
{
// Look for nested object
if( propertyInfo.PropertyType.IsClass
&& (propertyInfo.PropertyType != typeof( Transform ))
&& !propertyInfo.PropertyType.Equals( typeof( string ) ) )
{
// We have a Collection/List of T.
if( propertyInfo.PropertyType.IsGenericType )
{
// Clone sub-objects if the T are non-primitive types objects.
var arg = propertyInfo.PropertyType.GetGenericArguments().FirstOrDefault();
if( (arg != null) && !arg.IsPrimitive && !arg.Equals( typeof( String ) ) && !arg.IsEnum )
{
var nestedObject = this.Clone( propertyInfoValue );
propertyInfo.SetValue( result, nestedObject, null );
}
else
{
// copy object if the T are primitive types objects.
propertyInfo.SetValue( result, propertyInfoValue, null );
}
}
else
{
var nestedObject = this.Clone( propertyInfoValue );
if( nestedObject != null )
{
// For T object included in List/Collections, Add it to the List/Collection of T.
if( index != null )
{
result.GetType().GetMethod( "Add" ).Invoke( result, new[] { nestedObject } );
}
else
{
propertyInfo.SetValue( result, nestedObject, null );
}
}
}
}
else
{
// copy regular object
propertyInfo.SetValue( result, propertyInfoValue, null );
}
}
}
}
return result;
}
private object GenerateEditableKeyValuePair( object source )
{
var sourceType = source.GetType();
if( (sourceType.GetGenericArguments() == null) || (sourceType.GetGenericArguments().GetLength( 0 ) != 2) )
return null;
var propInfoKey = sourceType.GetProperty( "Key" );
var propInfoValue = sourceType.GetProperty( "Value" );
if( (propInfoKey != null) && (propInfoValue != null) )
{
return ListUtilities.CreateEditableKeyValuePair( propInfoKey.GetValue( source, null )
, sourceType.GetGenericArguments()[ 0 ]
, propInfoValue.GetValue( source, null )
, sourceType.GetGenericArguments()[ 1 ] );
}
return null;
}
private bool AreDictionaryKeysValid()
{
var keys = _collectionControl.Items.Select( x =>
{
var keyType = x.GetType().GetProperty( "Key" );
if( keyType != null )
{
return keyType.GetValue( x, null );
}
return null;
} );
return (keys.Distinct().Count() == _collectionControl.Items.Count )
&& keys.All( x => x != null );
}
#endregion
}
}

View File

@@ -0,0 +1,74 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Globalization;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.Converters
{
/// <summary>
/// This multi-value converter is used in the CollectionControl template
/// to determine the list of possible new item types that will be shown in the combo box.
///
/// If the second value (i.e., CollectionControl.NewItemTypes) is not null, this list will be used.
/// Otherwise, if the first value (i.e., CollectionControl.ItemsSourceType) is a "IList&lt;T&gt;"
/// type, the new item type list will contain "T".
///
/// </summary>
public class NewItemTypesComboBoxConverter : IMultiValueConverter
{
public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )
{
if( values.Length != 2 )
throw new ArgumentException("The 'values' argument should contain 2 objects.");
if( values[ 1 ] != null )
{
if( !values[ 1 ].GetType().IsGenericType || !(values[ 1 ].GetType().GetGenericArguments().First().GetType() is Type) )
throw new ArgumentException( "The 'value' argument is not of the correct type." );
return values[ 1 ];
}
else if( values[ 0 ] != null )
{
if( !( values[ 0 ].GetType() is Type ) )
throw new ArgumentException( "The 'value' argument is not of the correct type." );
List<Type> types = new List<Type>();
Type listType = ListUtilities.GetListItemType( ( Type )values[ 0 ] );
if( listType != null )
{
types.Add( listType );
}
return types;
}
return null;
}
public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,52 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xceed.Wpf.Toolkit.Core;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class ItemAddingEventArgs : CancelRoutedEventArgs
{
#region Constructor
public ItemAddingEventArgs( RoutedEvent itemAddingEvent, object itemAdding )
: base( itemAddingEvent )
{
Item = itemAdding;
}
#endregion
#region Properties
#region Item Property
public object Item
{
get;
set;
}
#endregion
#endregion //Properties
}
}

View File

@@ -0,0 +1,56 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xceed.Wpf.Toolkit.Core;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class ItemDeletingEventArgs : CancelRoutedEventArgs
{
#region Private Members
private object _item;
#endregion
#region Constructor
public ItemDeletingEventArgs( RoutedEvent itemDeletingEvent, object itemDeleting )
: base( itemDeletingEvent )
{
_item = itemDeleting;
}
#region Property Item
public object Item
{
get
{
return _item;
}
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,55 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class ItemEventArgs : RoutedEventArgs
{
#region Protected Members
private object _item;
#endregion
#region Constructor
internal ItemEventArgs( RoutedEvent routedEvent, object newItem )
: base( routedEvent )
{
_item = newItem;
}
#endregion
#region Property Item
public object Item
{
get
{
return _item;
}
}
#endregion
}
}

View File

@@ -0,0 +1,302 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace Xceed.Wpf.Toolkit
{
public class PrimitiveTypeCollectionControl : ContentControl
{
#region Members
bool _surpressTextChanged;
bool _conversionFailed;
#endregion //Members
#region Properties
#region IsOpen
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register( "IsOpen", typeof( bool ), typeof( PrimitiveTypeCollectionControl ), new UIPropertyMetadata( false, OnIsOpenChanged ) );
public bool IsOpen
{
get
{
return ( bool )GetValue( IsOpenProperty );
}
set
{
SetValue( IsOpenProperty, value );
}
}
private static void OnIsOpenChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PrimitiveTypeCollectionControl primitiveTypeCollectionControl = o as PrimitiveTypeCollectionControl;
if( primitiveTypeCollectionControl != null )
primitiveTypeCollectionControl.OnIsOpenChanged( ( bool )e.OldValue, ( bool )e.NewValue );
}
protected virtual void OnIsOpenChanged( bool oldValue, bool newValue )
{
}
#endregion //IsOpen
#region ItemsSource
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( "ItemsSource", typeof( IList ), typeof( PrimitiveTypeCollectionControl ), new UIPropertyMetadata( null, OnItemsSourceChanged ) );
public IList ItemsSource
{
get
{
return ( IList )GetValue( ItemsSourceProperty );
}
set
{
SetValue( ItemsSourceProperty, value );
}
}
private static void OnItemsSourceChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PrimitiveTypeCollectionControl primitiveTypeCollectionControl = o as PrimitiveTypeCollectionControl;
if( primitiveTypeCollectionControl != null )
primitiveTypeCollectionControl.OnItemsSourceChanged( ( IList )e.OldValue, ( IList )e.NewValue );
}
protected virtual void OnItemsSourceChanged( IList oldValue, IList newValue )
{
if( newValue == null )
return;
if( ItemsSourceType == null )
ItemsSourceType = newValue.GetType();
if( ItemType == null && newValue.GetType().ContainsGenericParameters )
ItemType = newValue.GetType().GetGenericArguments()[ 0 ];
SetText( newValue );
}
#endregion //ItemsSource
#region IsReadOnly
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( PrimitiveTypeCollectionControl ), new UIPropertyMetadata( false ) );
public bool IsReadOnly
{
get { return ( bool )GetValue( IsReadOnlyProperty ); }
set { SetValue( IsReadOnlyProperty, value ); }
}
#endregion //IsReadOnly
#region ItemsSourceType
public static readonly DependencyProperty ItemsSourceTypeProperty = DependencyProperty.Register( "ItemsSourceType", typeof( Type ), typeof( PrimitiveTypeCollectionControl ), new UIPropertyMetadata( null ) );
public Type ItemsSourceType
{
get
{
return ( Type )GetValue( ItemsSourceTypeProperty );
}
set
{
SetValue( ItemsSourceTypeProperty, value );
}
}
#endregion ItemsSourceType
#region ItemType
public static readonly DependencyProperty ItemTypeProperty = DependencyProperty.Register( "ItemType", typeof( Type ), typeof( PrimitiveTypeCollectionControl ), new UIPropertyMetadata( null ) );
public Type ItemType
{
get
{
return ( Type )GetValue( ItemTypeProperty );
}
set
{
SetValue( ItemTypeProperty, value );
}
}
#endregion ItemType
#region Text
public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof( string ), typeof( PrimitiveTypeCollectionControl ), new UIPropertyMetadata( null, OnTextChanged ) );
public string Text
{
get
{
return ( string )GetValue( TextProperty );
}
set
{
SetValue( TextProperty, value );
}
}
private static void OnTextChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PrimitiveTypeCollectionControl primitiveTypeCollectionControl = o as PrimitiveTypeCollectionControl;
if( primitiveTypeCollectionControl != null )
primitiveTypeCollectionControl.OnTextChanged( ( string )e.OldValue, ( string )e.NewValue );
}
protected virtual void OnTextChanged( string oldValue, string newValue )
{
if( !_surpressTextChanged )
PersistChanges();
}
#endregion //Text
#endregion //Properties
#region Constructors
static PrimitiveTypeCollectionControl()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PrimitiveTypeCollectionControl ), new FrameworkPropertyMetadata( typeof( PrimitiveTypeCollectionControl ) ) );
}
public PrimitiveTypeCollectionControl()
{
}
#endregion //Constructors
#region Methods
private void PersistChanges()
{
IList list = ComputeItemsSource();
if( list == null )
return;
IList items = ComputeItems();
//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 );
};
// if something went wrong during conversion we want to reload the text to show only valid entries
if( _conversionFailed )
SetText( list );
}
private IList ComputeItems()
{
IList items = new List<object>();
if( ItemType == null )
return items;
string[] textArray = Text.Split( '\n' );
foreach( string s in textArray )
{
string valueString = s.TrimEnd( '\r' );
if( !String.IsNullOrEmpty( valueString ) )
{
object value = null;
try
{
if( ItemType.IsEnum )
{
value = Enum.Parse( ItemType, valueString );
}
else
{
value = Convert.ChangeType( valueString, ItemType );
}
}
catch
{
//a conversion failed
_conversionFailed = true;
}
if( value != null )
items.Add( value );
}
}
return items;
}
private IList ComputeItemsSource()
{
if( ItemsSource == null )
{
// Save current text since creating the ItemsSource will reset it
string currentText = this.Text;
ItemsSource = CreateItemsSource();
this.Text = currentText;
}
return ItemsSource;
}
private IList CreateItemsSource()
{
IList list = null;
if( ItemsSourceType != null )
{
ConstructorInfo constructor = ItemsSourceType.GetConstructor( Type.EmptyTypes );
list = ( IList )constructor.Invoke( null );
}
return list;
}
private void SetText( IEnumerable collection )
{
_surpressTextChanged = true;
StringBuilder builder = new StringBuilder();
foreach( object obj2 in collection )
{
builder.Append( obj2.ToString() );
builder.AppendLine();
}
Text = builder.ToString().Trim();
_surpressTextChanged = false;
}
#endregion //Methods
}
}

View File

@@ -0,0 +1,260 @@
<!--***********************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
**********************************************************************************-->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xceed.Wpf.Toolkit"
xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters"
xmlns:colconv="clr-namespace:Xceed.Wpf.Toolkit.Converters"
xmlns:themes="clr-namespace:Xceed.Wpf.Toolkit.Themes"
xmlns:chrome="clr-namespace:Xceed.Wpf.Toolkit.Chromes"
xmlns:pg="clr-namespace:Xceed.Wpf.Toolkit.PropertyGrid">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Themes/Aero2/Glyphs.xaml" />
</ResourceDictionary.MergedDictionaries>
<conv:InverseBoolConverter x:Key="InverseBoolConverter" />
<conv:ObjectTypeToNameConverter x:Key="ObjectTypeToNameConverter" />
<colconv:NewItemTypesComboBoxConverter x:Key="NewItemTypesComboBoxConverter" />
<Style x:Key="CollectionControlButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.6" />
</Trigger>
</Style.Triggers>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Height" Value="26" />
<Setter Property="Width" Value="26" />
</Style>
<Style TargetType="{x:Type local:CollectionControl}">
<Style.Resources>
<Style TargetType="ListBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource ObjectTypeToNameConverter}}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CollectionControl}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="1.5*" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Margin="0,0,0,5" Text="Select type:" />
<ComboBox x:Name="PART_NewItemTypesComboBox"
Grid.Row="1"
Margin="0,0,0,3"
HorizontalAlignment="Stretch"
DisplayMemberPath="Name">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource NewItemTypesComboBoxConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ItemsSourceType" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="NewItemTypes" />
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
<Button Margin="3,0,0,3"
Grid.Row="1"
Grid.Column="1"
Padding="5,0"
Content="Add"
Command="New"
CommandParameter="{Binding SelectedItem, ElementName=PART_NewItemTypesComboBox}" />
<ListBox x:Name="PART_ListBox"
Grid.Row="2"
Grid.ColumnSpan="2"
ItemsSource="{Binding Items, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}"
SelectedIndex="0">
</ListBox>
<StackPanel Margin="7,2,0,0" VerticalAlignment="Top" Grid.Column="2" Grid.Row="2">
<Button Style="{StaticResource CollectionControlButtonStyle}"
Command="ComponentCommands.MoveUp"
CommandParameter="{Binding SelectedItem, ElementName=PART_ListBox}">
<Path Fill="#FF000000" Data="F0 M 6,0 L 12,7 8,7 8,12 4,12 4,7 0,7 Z" />
</Button>
<Button Margin="0,1,0,0"
Style="{StaticResource CollectionControlButtonStyle}"
Command="ComponentCommands.MoveDown"
CommandParameter="{Binding SelectedItem, ElementName=PART_ListBox}">
<Path Fill="#FF000000" Data="F0 M 4,0 L 8,0 8,5 12,5 6,12 0,5 4,5 Z" />
</Button>
<Button Margin="0,7,0,0"
Style="{StaticResource CollectionControlButtonStyle}"
Command="Delete"
CommandParameter="{Binding SelectedItem, ElementName=PART_ListBox}">
<Image Stretch="None" Height="16" Width="16" Margin="1" Source="./../Images/Delete16.png" />
</Button>
</StackPanel>
</Grid>
<Grid Column="1" Margin="20,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Column="1" Text="Properties:" />
<pg:PropertyGrid x:Name="PART_PropertyGrid"
Grid.Row="1"
Grid.Column="1"
Margin="0,5,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SelectedObject="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"
TargetName="PART_NewItemTypesComboBox"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PrimitiveTypeCollectionControl" TargetType="{x:Type local:PrimitiveTypeCollectionControl}">
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static themes:ResourceKeys.ControlNormalBorderKey}}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1,1,0,1" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Padding" Value="2,0,0,0" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PrimitiveTypeCollectionControl}">
<local:MultiLineTextEditor Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
IsOpen="{TemplateBinding IsOpen}"
IsReadOnly="{TemplateBinding IsReadOnly}"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
DropDownWidth="{TemplateBinding ActualWidth}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static themes:ResourceKeys.ControlMouseOverBorderKey}}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static themes:ResourceKeys.ControlSelectedBorderKey}}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{DynamicResource {x:Static themes:ResourceKeys.ControlDisabledBackgroundKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:PrimitiveTypeCollectionControl}" BasedOn="{StaticResource PrimitiveTypeCollectionControl}" />
<Style x:Key="CollectionControlButton" TargetType="{x:Type local:CollectionControlButton}">
<Setter Property="Background" Value="White" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="2,0,0,0" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Content" Value="(Collection)"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="MinHeight" Value="22"/>
<Setter Property="IsTabStop" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid SnapsToDevicePixels="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="True">
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Border>
<chrome:ButtonChrome x:Name="ToggleButtonChrome"
Grid.Column="1"
CornerRadius="0,2.75,2.75,0"
RenderEnabled="{Binding IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:CollectionControlButton}}"
RenderMouseOver="{TemplateBinding IsMouseOver}">
<Grid x:Name="arrowGlyph" IsHitTestVisible="False" Grid.Column="1" Margin="5">
<Path x:Name="Arrow"
Width="9"
Height="5"
Data="{StaticResource DownArrowGeometry}"
Fill="#FF000000"
Margin="0,1,0,0"/>
</Grid>
</chrome:ButtonChrome>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF" />
<Setter Property="Foreground" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:CollectionControlButton}"
BasedOn="{StaticResource CollectionControlButton}" />
</ResourceDictionary>

View File

@@ -0,0 +1,307 @@
<!--***********************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 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
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
**********************************************************************************-->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xceed.Wpf.Toolkit"
xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters"
xmlns:colconv="clr-namespace:Xceed.Wpf.Toolkit.Converters"
xmlns:chrome="clr-namespace:Xceed.Wpf.Toolkit.Chromes"
xmlns:pg="clr-namespace:Xceed.Wpf.Toolkit.PropertyGrid">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\..\Themes\Generic\Glyphs.xaml" />
</ResourceDictionary.MergedDictionaries>
<conv:InverseBoolConverter x:Key="InverseBoolConverter" />
<conv:ObjectTypeToNameConverter x:Key="ObjectTypeToNameConverter" />
<colconv:NewItemTypesComboBoxConverter x:Key="NewItemTypesComboBoxConverter" />
<Style x:Key="CollectionControlButtonStyle"
TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Opacity"
Value="0.6" />
</Trigger>
</Style.Triggers>
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Height"
Value="26" />
<Setter Property="Width"
Value="26" />
</Style>
<Style TargetType="{x:Type local:CollectionControl}">
<Style.Resources>
<Style TargetType="ListBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource ObjectTypeToNameConverter}}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CollectionControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="1.5*" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Margin="0,0,0,5"
Text="Select type:" />
<ComboBox x:Name="PART_NewItemTypesComboBox"
Grid.Row="1"
Margin="0,0,0,3"
HorizontalAlignment="Stretch"
DisplayMemberPath="Name">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource NewItemTypesComboBoxConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="ItemsSourceType" />
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="NewItemTypes" />
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
<Button Margin="3,0,0,3"
Grid.Row="1"
Grid.Column="1"
Padding="5,0"
Content="Add"
Command="New"
CommandParameter="{Binding SelectedItem, ElementName=PART_NewItemTypesComboBox}" />
<ListBox x:Name="PART_ListBox"
Grid.Row="2"
Grid.ColumnSpan="2"
ItemsSource="{Binding Items, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}"
SelectedIndex="0">
</ListBox>
<StackPanel Margin="7,2,0,0"
VerticalAlignment="Top"
Grid.Column="2"
Grid.Row="2">
<Button Style="{StaticResource CollectionControlButtonStyle}"
Command="ComponentCommands.MoveUp"
CommandParameter="{Binding SelectedItem, ElementName=PART_ListBox}">
<Path Fill="#FF404040"
Data="F0 M 6,0 L 12,7 8,7 8,12 4,12 4,7 0,7 Z" />
</Button>
<Button Margin="0,1,0,0"
Style="{StaticResource CollectionControlButtonStyle}"
Command="ComponentCommands.MoveDown"
CommandParameter="{Binding SelectedItem, ElementName=PART_ListBox}">
<Path Fill="#FF404040"
Data="F0 M 4,0 L 8,0 8,5 12,5 6,12 0,5 4,5 Z" />
</Button>
<Button Margin="0,7,0,0"
Style="{StaticResource CollectionControlButtonStyle}"
Command="Delete"
CommandParameter="{Binding SelectedItem, ElementName=PART_ListBox}">
<Image Stretch="None"
Height="16"
Width="16"
Margin="1"
Source="./../Images/Delete16.png" />
</Button>
</StackPanel>
</Grid>
<Grid Column="1"
Margin="20,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Column="1"
Text="Properties:" />
<pg:PropertyGrid x:Name="PART_PropertyGrid"
Grid.Row="1"
Grid.Column="1"
Margin="0,5,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
SelectedObject="{Binding SelectedItem, RelativeSource={RelativeSource TemplatedParent}}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"
TargetName="PART_NewItemTypesComboBox" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PrimitiveTypeCollectionControl"
TargetType="{x:Type local:PrimitiveTypeCollectionControl}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9"
Offset="0" />
<GradientStop Color="#FF8399A9"
Offset="0.375" />
<GradientStop Color="#FF718597"
Offset="0.375" />
<GradientStop Color="#FF617584"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="1,1,0,1" />
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="Padding"
Value="2,0,0,0" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PrimitiveTypeCollectionControl}">
<local:MultiLineTextEditor Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
IsOpen="{TemplateBinding IsOpen}"
IsReadOnly="{TemplateBinding IsReadOnly}"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
DropDownWidth="{TemplateBinding ActualWidth}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:PrimitiveTypeCollectionControl}"
BasedOn="{StaticResource PrimitiveTypeCollectionControl}" />
<Style x:Key="CollectionControlButton"
TargetType="{x:Type local:CollectionControlButton}">
<Setter Property="Background"
Value="White" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Padding"
Value="2,0,0,0" />
<Setter Property="HorizontalContentAlignment"
Value="Left" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Content"
Value="(Collection)" />
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="MinHeight"
Value="22" />
<Setter Property="IsTabStop"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid SnapsToDevicePixels="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="True">
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Border>
<chrome:ButtonChrome x:Name="ToggleButtonChrome"
Grid.Column="1"
CornerRadius="0,2.75,2.75,0"
RenderEnabled="{Binding IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:CollectionControlButton}}"
RenderMouseOver="{TemplateBinding IsMouseOver}">
<Grid x:Name="arrowGlyph"
IsHitTestVisible="False"
Grid.Column="1"
Margin="5">
<Path x:Name="Arrow"
Width="9"
Height="5"
Data="{StaticResource DownArrowGeometry}"
Fill="#FF000000"
Margin="0,1,0,0"/>
</Grid>
</chrome:ButtonChrome>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Fill"
TargetName="Arrow"
Value="#AFAFAF" />
<Setter Property="Foreground"
Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:CollectionControlButton}"
BasedOn="{StaticResource CollectionControlButton}" />
</ResourceDictionary>