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

View File

@@ -0,0 +1,76 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Attributes
{
[AttributeUsage( AttributeTargets.Class, AllowMultiple = true )]
public class CategoryOrderAttribute : Attribute
{
#region Properties
#region Order
public int Order
{
get;
set;
}
#endregion
#region Category
public virtual string Category
{
get
{
return CategoryValue;
}
}
#endregion
#region CategoryValue
public string CategoryValue
{
get;
private set;
}
#endregion
#endregion
#region constructor
public CategoryOrderAttribute()
{
}
public CategoryOrderAttribute( string categoryName, int order )
:this()
{
CategoryValue = categoryName;
Order = order;
}
#endregion
}
}

View File

@@ -0,0 +1,39 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Attributes
{
public class ExpandableObjectAttribute : Attribute
{
#region Constructors
public ExpandableObjectAttribute()
{
}
#endregion
#region Properties
#endregion
}
}

View File

@@ -0,0 +1,58 @@
/*************************************************************************************
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.Collections.Generic;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Attributes
{
public interface IItemsSource
{
ItemCollection GetValues();
}
public class Item
{
public string DisplayName
{
get;
set;
}
public object Value
{
get;
set;
}
}
public class ItemCollection : List<Item>
{
public void Add( object value )
{
Item item = new Item();
item.DisplayName = value.ToString();
item.Value = value;
base.Add( item );
}
public void Add( object value, string displayName )
{
Item newItem = new Item();
newItem.DisplayName = displayName;
newItem.Value = value;
base.Add( newItem );
}
}
}

View File

@@ -0,0 +1,38 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Attributes
{
public class ItemsSourceAttribute : Attribute
{
public Type Type
{
get;
set;
}
public ItemsSourceAttribute( Type type )
{
var valueSourceInterface = type.GetInterface( typeof( IItemsSource ).FullName );
if( valueSourceInterface == null )
throw new ArgumentException( "Type must implement the IItemsSource interface.", "type" );
Type = type;
}
}
}

View File

@@ -0,0 +1,45 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Attributes
{
/// <summary>
/// This attribute can decorate the collection properties (i.e., IList)
/// of your selected object in order to control the types that will be allowed
/// to be instantiated in the CollectionControl.
/// </summary>
[AttributeUsage( AttributeTargets.Property, AllowMultiple = false, Inherited = true )]
public class NewItemTypesAttribute : Attribute
{
public IList<Type> Types
{
get;
set;
}
public NewItemTypesAttribute( params Type[] types )
{
this.Types = new List<Type>( types );
}
public NewItemTypesAttribute()
{
}
}
}

View File

@@ -0,0 +1,70 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Attributes
{
public enum UsageContextEnum
{
Alphabetical,
Categorized,
Both
}
[AttributeUsage( AttributeTargets.Property, AllowMultiple = true, Inherited = true )]
public class PropertyOrderAttribute : Attribute
{
#region Properties
public int Order
{
get;
set;
}
public UsageContextEnum UsageContext
{
get;
set;
}
public override object TypeId
{
get
{
return this;
}
}
#endregion
#region Initialization
public PropertyOrderAttribute( int order )
: this( order, UsageContextEnum.Both )
{
}
public PropertyOrderAttribute( int order, UsageContextEnum usageContext )
{
Order = order;
UsageContext = usageContext;
}
#endregion
}
}

View File

@@ -0,0 +1,65 @@
/*************************************************************************************
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.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public class CategoryGroupStyleSelector : StyleSelector
{
public Style SingleDefaultCategoryItemGroupStyle
{
get;
set;
}
public Style ItemGroupStyle
{
get;
set;
}
public override Style SelectStyle( object item, DependencyObject container )
{
var group = item as CollectionViewGroup;
// Category is not "Misc" => use regular ItemGroupStyle
if( !group.Name.Equals( CategoryAttribute.Default.Category ) )
return this.ItemGroupStyle;
// Category is "Misc"
while( container != null )
{
container = VisualTreeHelper.GetParent( container );
if( container is ItemsControl )
break;
}
var itemsControl = container as ItemsControl;
if( itemsControl != null )
{
// Category is "Misc" and this is the only category => use SingleDefaultCategoryItemGroupContainerStyle
if( (itemsControl.Items.Count > 0) && (itemsControl.Items.Groups.Count == 1) )
return this.SingleDefaultCategoryItemGroupStyle;
}
// Category is "Misc" and this is NOT the only category => use regular ItemGroupStyle
return this.ItemGroupStyle;
}
}
}

View File

@@ -0,0 +1,32 @@
/*************************************************************************************
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.Windows.Input;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Commands
{
public class PropertyGridCommands
{
private static RoutedCommand _clearFilterCommand = new RoutedCommand();
public static RoutedCommand ClearFilter
{
get
{
return _clearFilterCommand;
}
}
}
}

View File

@@ -0,0 +1,32 @@
/*************************************************************************************
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.Windows.Input;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Commands
{
public static class PropertyItemCommands
{
private static RoutedCommand _resetValueCommand = new RoutedCommand();
public static RoutedCommand ResetValue
{
get
{
return _resetValueCommand;
}
}
}
}

View File

@@ -0,0 +1,58 @@
/*************************************************************************************
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.Controls;
using System.ComponentModel;
using Xceed.Wpf.Toolkit.Core.Utilities;
using System.Globalization;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal class CommonPropertyExceptionValidationRule : ValidationRule
{
private TypeConverter _propertyTypeConverter;
private Type _type;
internal CommonPropertyExceptionValidationRule( Type type )
{
_propertyTypeConverter = TypeDescriptor.GetConverter( type );
_type = type;
}
public override ValidationResult Validate( object value, CultureInfo cultureInfo )
{
ValidationResult result = new ValidationResult( true, null );
if( GeneralUtilities.CanConvertValue( value, _type ) )
{
try
{
_propertyTypeConverter.ConvertFrom( value );
}
catch( Exception e )
{
// Will display a red border in propertyGrid
result = new ValidationResult( false, e.Message );
}
}
return result;
}
}
}

View File

@@ -0,0 +1,229 @@
/*************************************************************************************
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.Collections.Generic;
using System.Collections;
using System;
using System.Windows;
using System.ComponentModel;
using Xceed.Wpf.Toolkit.Core.Utilities;
using System.Windows.Data;
using System.Diagnostics;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal abstract class ContainerHelperBase
{
protected readonly IPropertyContainer PropertyContainer;
public ContainerHelperBase(IPropertyContainer propertyContainer)
{
if( propertyContainer == null )
throw new ArgumentNullException( "propertyContainer" );
PropertyContainer = propertyContainer;
var propChange = propertyContainer as INotifyPropertyChanged;
if( propChange != null )
{
propChange.PropertyChanged += new PropertyChangedEventHandler( OnPropertyContainerPropertyChanged );
}
}
#region IsGenerated attached property
internal static readonly DependencyProperty IsGeneratedProperty = DependencyProperty.RegisterAttached(
"IsGenerated",
typeof( bool ),
typeof( ContainerHelperBase ),
new PropertyMetadata( false ) );
internal static bool GetIsGenerated( DependencyObject obj )
{
return ( bool )obj.GetValue( ContainerHelperBase.IsGeneratedProperty );
}
internal static void SetIsGenerated( DependencyObject obj, bool value )
{
obj.SetValue( ContainerHelperBase.IsGeneratedProperty, value );
}
#endregion IsGenerated attached property
public abstract IList Properties
{
get;
}
internal ItemsControl ChildrenItemsControl
{
get;
set;
}
public virtual void ClearHelper()
{
var propChange = PropertyContainer as INotifyPropertyChanged;
if( propChange != null )
{
propChange.PropertyChanged -= new PropertyChangedEventHandler( OnPropertyContainerPropertyChanged );
}
// Calling RemoveAll() will force the ItemsContol displaying the
// properties to clear all the current container (i.e., ClearContainerForItem).
// This will make the call at "ClearChildrenPropertyItem" for every prepared
// container. Fortunately, the ItemsContainer will not re-prepare the items yet
// (i.e., probably made on next measure pass), allowing us to set up the new
// parent helper.
if( ChildrenItemsControl != null )
{
( ( IItemContainerGenerator )ChildrenItemsControl.ItemContainerGenerator ).RemoveAll();
}
}
public virtual void PrepareChildrenPropertyItem( PropertyItemBase propertyItem, object item )
{
// Initialize the parent node
propertyItem.ParentNode = PropertyContainer;
PropertyGrid.RaisePreparePropertyItemEvent( ( UIElement )PropertyContainer, propertyItem, item );
}
public virtual void ClearChildrenPropertyItem( PropertyItemBase propertyItem, object item )
{
propertyItem.ParentNode = null;
PropertyGrid.RaiseClearPropertyItemEvent( ( UIElement )PropertyContainer, propertyItem, item );
}
protected FrameworkElement GenerateCustomEditingElement( Type definitionKey, PropertyItemBase propertyItem )
{
return ( PropertyContainer.EditorDefinitions != null )
? this.CreateCustomEditor( PropertyContainer.EditorDefinitions.GetRecursiveBaseTypes( definitionKey ), propertyItem )
: null;
}
protected FrameworkElement GenerateCustomEditingElement( object definitionKey, PropertyItemBase propertyItem )
{
return ( PropertyContainer.EditorDefinitions != null )
? this.CreateCustomEditor( PropertyContainer.EditorDefinitions[ definitionKey ], propertyItem )
: null;
}
protected FrameworkElement CreateCustomEditor( EditorDefinitionBase customEditor, PropertyItemBase propertyItem )
{
return ( customEditor != null )
? customEditor.GenerateEditingElementInternal( propertyItem )
: null;
}
protected virtual void OnPropertyContainerPropertyChanged( object sender, PropertyChangedEventArgs e )
{
var propertyName = e.PropertyName;
IPropertyContainer ps = null;
if( propertyName == ReflectionHelper.GetPropertyOrFieldName( () => ps.FilterInfo ) )
{
this.OnFilterChanged();
}
else if( propertyName == ReflectionHelper.GetPropertyOrFieldName( () => ps.IsCategorized ) )
{
this.OnCategorizationChanged();
}
else if( propertyName == ReflectionHelper.GetPropertyOrFieldName( () => ps.AutoGenerateProperties ) )
{
this.OnAutoGeneratePropertiesChanged();
}
else if( propertyName == ReflectionHelper.GetPropertyOrFieldName( () => ps.HideInheritedProperties ) )
{
this.OnHideInheritedPropertiesChanged();
}
else if(propertyName == ReflectionHelper.GetPropertyOrFieldName( () => ps.EditorDefinitions ))
{
this.OnEditorDefinitionsChanged();
}
else if(propertyName == ReflectionHelper.GetPropertyOrFieldName( () => ps.PropertyDefinitions ))
{
this.OnPropertyDefinitionsChanged();
}
}
protected virtual void OnCategorizationChanged() { }
protected virtual void OnFilterChanged() { }
protected virtual void OnAutoGeneratePropertiesChanged() { }
protected virtual void OnHideInheritedPropertiesChanged() { }
protected virtual void OnEditorDefinitionsChanged() { }
protected virtual void OnPropertyDefinitionsChanged() { }
public virtual void OnEndInit() { }
public abstract PropertyItemBase ContainerFromItem( object item );
public abstract object ItemFromContainer( PropertyItemBase container );
public abstract Binding CreateChildrenDefaultBinding( PropertyItemBase propertyItem );
public virtual void NotifyEditorDefinitionsCollectionChanged() { }
public virtual void NotifyPropertyDefinitionsCollectionChanged() { }
public abstract void UpdateValuesFromSource();
protected internal virtual void SetPropertiesExpansion( bool isExpanded )
{
foreach( var item in this.Properties )
{
var propertyItem = item as PropertyItemBase;
if( (propertyItem != null) && propertyItem.IsExpandable )
{
if( propertyItem.ContainerHelper != null )
{
propertyItem.ContainerHelper.SetPropertiesExpansion( isExpanded );
}
propertyItem.IsExpanded = isExpanded;
}
}
}
protected internal virtual void SetPropertiesExpansion( string propertyName, bool isExpanded )
{
foreach( var item in this.Properties )
{
var propertyItem = item as PropertyItemBase;
if( (propertyItem != null) && propertyItem.IsExpandable )
{
if( propertyItem.DisplayName == propertyName )
{
propertyItem.IsExpanded = isExpanded;
break;
}
if( propertyItem.ContainerHelper != null )
{
propertyItem.ContainerHelper.SetPropertiesExpansion( propertyName, isExpanded );
}
}
}
}
}
}

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.Globalization;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
/// <summary>
/// Converts a TimeSpan value to a DateTime value.
///
/// This converter can be used in conjunction with a TimePicker in order
/// to create a TimeSpan edit control.
/// </summary>
public sealed class EditorTimeSpanConverter : IValueConverter
{
public bool AllowNulls { get; set; }
object IValueConverter.Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( this.AllowNulls && value == null )
return null;
TimeSpan timeSpan = ( value != null ) ? ( TimeSpan )value : TimeSpan.Zero;
return DateTime.Today + timeSpan;
}
object IValueConverter.ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
if( this.AllowNulls && value == null )
return null;
return ( value != null )
? ( ( DateTime )value ).TimeOfDay
: TimeSpan.Zero;
}
}
}

View File

@@ -0,0 +1,36 @@
/*************************************************************************************
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.Windows;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
public class ExpandableObjectMarginConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{
int childLevel = ( int )value;
return new Thickness( childLevel * 15, 0, 0, 0 );
}
public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,45 @@
/*************************************************************************************
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.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
public class IsDefaultCategoryConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
string categoryName = value as string;
if( categoryName != null )
{
return ( categoryName == CategoryAttribute.Default.Category );
}
return false;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,40 @@
/*************************************************************************************
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.Globalization;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
public class IsStringEmptyConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( value is string )
{
return string.IsNullOrEmpty( ( string )value );
}
return false;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,105 @@
/*************************************************************************************
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.ComponentModel;
using System.Collections;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
internal class ListConverter : TypeConverter
{
public override bool CanConvertFrom( ITypeDescriptorContext context, Type sourceType )
{
return true;
}
public override bool CanConvertTo( ITypeDescriptorContext context, Type destinationType )
{
return ( destinationType == typeof( string ) );
}
public override object ConvertFrom( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value )
{
if( value == null )
return null;
string names = value as string;
var list = new List<object>();
if( names == null && value != null )
{
list.Add( value );
}
else
{
if( names == null )
return null;
foreach( var name in names.Split( ',' ) )
{
list.Add( name.Trim() );
}
}
return new ReadOnlyCollection<object>( list );
}
public override object ConvertTo( ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType )
{
if( destinationType != typeof( string ) )
throw new InvalidOperationException( "Can only convert to string." );
IList strs = ( IList )value;
if( strs == null )
return null;
StringBuilder sb = new StringBuilder();
bool first = true;
foreach( object o in strs )
{
if( o == null )
throw new InvalidOperationException( "Property names cannot be null." );
string s = o as string;
if( s == null )
throw new InvalidOperationException( "Does not support serialization of non-string property names." );
if( s.Contains( ',' ) )
throw new InvalidOperationException( "Property names cannot contain commas." );
if( s.Trim().Length != s.Length )
throw new InvalidOperationException( "Property names cannot start or end with whitespace characters." );
if( !first )
{
sb.Append( ", " );
}
first = false;
sb.Append( s );
}
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,43 @@
/*************************************************************************************
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.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
public class ObjectToUIElementConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( value is UIElement )
return value;
return new Control();
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,109 @@
/*************************************************************************************
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 System.ComponentModel;
using System.Windows;
using System.Reflection;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
public class SelectedObjectConverter : IValueConverter
{
private const string ValidParameterMessage = @"parameter must be one of the following strings: 'Type', 'TypeName', 'SelectedObjectName'";
#region IValueConverter Members
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( parameter == null )
throw new ArgumentNullException( "parameter" );
if( !( parameter is string ) )
throw new ArgumentException( SelectedObjectConverter.ValidParameterMessage );
if( this.CompareParam(parameter, "Type") )
{
return this.ConvertToType( value, culture );
}
else if( this.CompareParam( parameter, "TypeName" ) )
{
return this.ConvertToTypeName( value, culture );
}
else if( this.CompareParam( parameter, "SelectedObjectName" ) )
{
return this.ConvertToSelectedObjectName( value, culture );
}
else
{
throw new ArgumentException( SelectedObjectConverter.ValidParameterMessage );
}
}
private bool CompareParam(object parameter, string parameterValue )
{
return string.Compare( ( string )parameter, parameterValue, true ) == 0;
}
private object ConvertToType( object value, CultureInfo culture )
{
return ( value != null )
? value.GetType()
: null;
}
private object ConvertToTypeName( object value, CultureInfo culture )
{
if( value == null )
return string.Empty;
Type newType = value.GetType();
DisplayNameAttribute displayNameAttribute = newType.GetCustomAttributes( false ).OfType<DisplayNameAttribute>().FirstOrDefault();
return (displayNameAttribute == null)
? newType.Name
: displayNameAttribute.DisplayName;
}
private object ConvertToSelectedObjectName( object value, CultureInfo culture )
{
if( value == null )
return String.Empty;
Type newType = value.GetType();
PropertyInfo[] properties = newType.GetProperties();
foreach( PropertyInfo property in properties )
{
if( property.Name == "Name" )
return property.GetValue( value, null );
}
return String.Empty;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,187 @@
/*************************************************************************************
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;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
/// <summary>
/// Used when properties are provided using a list source of items (eg. Properties or PropertiesSource).
///
/// An instance of this class can be used as an item to easily customize the
/// display of the property directly by modifying the values of this class
/// (e.g., DisplayName, value, Category, etc.).
/// </summary>
public class CustomPropertyItem : PropertyItemBase
{
#region Constructors
internal CustomPropertyItem() { }
internal CustomPropertyItem( bool isPropertyGridCategorized, bool isSortedAlphabetically )
{
this.Init( isPropertyGridCategorized, isSortedAlphabetically );
}
#endregion
#region Properties
#region Category
public static readonly DependencyProperty CategoryProperty =
DependencyProperty.Register( "Category", typeof( string ), typeof( CustomPropertyItem ), new UIPropertyMetadata( null ) );
public string Category
{
get { return ( string )GetValue( CategoryProperty ); }
set { SetValue( CategoryProperty, value ); }
}
#endregion //Category
#region CategoryOrder
public int CategoryOrder
{
get
{
return _categoryOrder;
}
set
{
if( _categoryOrder != value )
{
_categoryOrder = value;
// Notify the parent helper since this property may affect ordering.
this.RaisePropertyChanged( () => this.CategoryOrder );
}
}
}
private int _categoryOrder;
#endregion //CategoryOrder
#region PropertyOrder
public static readonly DependencyProperty PropertyOrderProperty =
DependencyProperty.Register( "PropertyOrder", typeof( int ), typeof( CustomPropertyItem ), new UIPropertyMetadata( 0 ) );
public int PropertyOrder
{
get
{
return ( int )GetValue( PropertyOrderProperty );
}
set
{
SetValue( PropertyOrderProperty, value );
}
}
#endregion //PropertyOrder
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( object ), typeof( CustomPropertyItem ), new UIPropertyMetadata( null, OnValueChanged, OnCoerceValueChanged ) );
public object Value
{
get
{
return ( object )GetValue( ValueProperty );
}
set
{
SetValue( ValueProperty, value );
}
}
private static object OnCoerceValueChanged( DependencyObject o, object baseValue )
{
CustomPropertyItem prop = o as CustomPropertyItem;
if( prop != null )
return prop.OnCoerceValueChanged( baseValue );
return baseValue;
}
protected virtual object OnCoerceValueChanged( object baseValue )
{
return baseValue;
}
private static void OnValueChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
CustomPropertyItem propertyItem = o as CustomPropertyItem;
if( propertyItem != null )
{
propertyItem.OnValueChanged( ( object )e.OldValue, ( object )e.NewValue );
}
}
protected virtual void OnValueChanged( object oldValue, object newValue )
{
if( IsInitialized )
{
RaiseEvent( new PropertyValueChangedEventArgs( PropertyGrid.PropertyValueChangedEvent, this, oldValue, newValue ) );
}
}
#endregion //Value
#endregion
#region Overrides
protected override Type GetPropertyItemType()
{
return this.Value.GetType();
}
protected override void OnEditorChanged( FrameworkElement oldValue, FrameworkElement newValue )
{
if( oldValue != null )
oldValue.DataContext = null;
if( newValue != null )
newValue.DataContext = this;
}
#endregion
#region Private Methods
private void Init( bool isPropertyGridCategorized, bool isSortedAlphabetically )
{
_isPropertyGridCategorized = isPropertyGridCategorized;
_isSortedAlphabetically = isSortedAlphabetically;
}
#endregion
}
}

View File

@@ -0,0 +1,64 @@
/*************************************************************************************
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.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Xceed.Wpf.Toolkit.PropertyGrid.Converters;
using System.Windows;
using Xceed.Wpf.Toolkit.Core.Utilities;
using System.Linq.Expressions;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public abstract class DefinitionBase : DependencyObject
{
private bool _isLocked;
internal bool IsLocked
{
get { return _isLocked; }
}
internal void ThrowIfLocked<TMember>( Expression<Func<TMember>> propertyExpression )
{
//In XAML, when using any properties of PropertyDefinition, the error of ThrowIfLocked is always thrown => prevent it !
if( DesignerProperties.GetIsInDesignMode( this ) )
return;
if( this.IsLocked )
{
string propertyName = ReflectionHelper.GetPropertyOrFieldName( propertyExpression );
string message = string.Format(
@"Cannot modify {0} once the definition has beed added to a collection.",
propertyName );
throw new InvalidOperationException( message );
}
}
internal virtual void Lock()
{
if( !_isLocked )
{
_isLocked = true;
}
}
}
}

View File

@@ -0,0 +1,70 @@
/*************************************************************************************
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.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public abstract class EditorDefinitionBase : PropertyDefinitionBase
{
internal EditorDefinitionBase() { }
internal FrameworkElement GenerateEditingElementInternal( PropertyItemBase propertyItem )
{
return this.GenerateEditingElement( propertyItem );
}
protected virtual FrameworkElement GenerateEditingElement( PropertyItemBase propertyItem ) { return null; }
internal void UpdateProperty( FrameworkElement element, DependencyProperty elementProp, DependencyProperty definitionProperty )
{
object currentValue = this.GetValue( definitionProperty );
object localValue = this.ReadLocalValue( definitionProperty );
object elementValue = element.GetValue( elementProp );
bool areEquals = false;
// Avoid setting values if it does not affect anything
// because setting a local value may prevent a style setter from being active.
if( localValue != DependencyProperty.UnsetValue )
{
if( ( elementValue != null ) && ( currentValue != null ) )
{
areEquals = ( elementValue.GetType().IsValueType && currentValue.GetType().IsValueType )
? elementValue.Equals( currentValue ) // Value Types
: currentValue == element.GetValue( elementProp ); // Reference Types
}
if( !areEquals )
{
element.SetValue( elementProp, currentValue );
}
else
{
element.ClearValue( elementProp );
}
}
}
}
}

View File

@@ -0,0 +1,47 @@
/*************************************************************************************
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.PropertyGrid
{
public class EditorTemplateDefinition : EditorDefinitionBase
{
#region EditingTemplate
public static readonly DependencyProperty EditingTemplateProperty =
DependencyProperty.Register( "EditingTemplate", typeof( DataTemplate ), typeof( EditorTemplateDefinition ), new UIPropertyMetadata( null ) );
public DataTemplate EditingTemplate
{
get { return ( DataTemplate )GetValue( EditingTemplateProperty ); }
set { SetValue( EditingTemplateProperty, value ); }
}
#endregion //EditingTemplate
protected override sealed FrameworkElement GenerateEditingElement( PropertyItemBase propertyItem )
{
return ( this.EditingTemplate != null )
? this.EditingTemplate.LoadContent() as FrameworkElement
: null;
}
}
}

View File

@@ -0,0 +1,113 @@
/*************************************************************************************
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.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Xceed.Wpf.Toolkit.PropertyGrid.Converters;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public abstract class PropertyDefinitionBase : DefinitionBase
{
#region Constructors
internal PropertyDefinitionBase()
{
_targetProperties = new List<object>();
this.PropertyDefinitions = new PropertyDefinitionCollection();
}
#endregion
#region Properties
#region TargetProperties
[TypeConverter(typeof(ListConverter))]
public IList TargetProperties
{
get { return _targetProperties; }
set
{
this.ThrowIfLocked( () => this.TargetProperties );
_targetProperties = value;
}
}
private IList _targetProperties;
#endregion
#region PropertyDefinitions
public PropertyDefinitionCollection PropertyDefinitions
{
get
{
return _propertyDefinitions;
}
set
{
this.ThrowIfLocked( () => this.PropertyDefinitions );
_propertyDefinitions = value;
}
}
private PropertyDefinitionCollection _propertyDefinitions;
#endregion //PropertyDefinitions
#endregion
#region Overrides
internal override void Lock()
{
if( this.IsLocked )
return;
base.Lock();
// Just create a new copy of the properties target to ensure
// that the list doesn't ever get modified.
List<object> newList = new List<object>();
if( _targetProperties != null )
{
foreach( object p in _targetProperties )
{
object prop = p;
// Convert all TargetPropertyType to Types
var targetType = prop as TargetPropertyType;
if( targetType != null )
{
prop = targetType.Type;
}
newList.Add( prop );
}
}
//In Designer Mode, the Designer is broken if using a ReadOnlyCollection
_targetProperties = DesignerProperties.GetIsInDesignMode( this )
? new Collection<object>( newList )
: new ReadOnlyCollection<object>( newList ) as IList;
}
#endregion
}
}

View File

@@ -0,0 +1,232 @@
/*************************************************************************************
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.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Markup.Primitives;
using System.Windows.Media;
using System.Windows.Media.Imaging;
#if !VS2008
using System.ComponentModel.DataAnnotations;
#endif
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using Xceed.Wpf.Toolkit.PropertyGrid.Commands;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
using System.Reflection;
using System.Globalization;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal class DescriptorPropertyDefinition : DescriptorPropertyDefinitionBase
{
#region Members
private object _selectedObject;
private PropertyDescriptor _propertyDescriptor;
private DependencyPropertyDescriptor _dpDescriptor;
private MarkupObject _markupObject;
#endregion
#region Constructor
internal DescriptorPropertyDefinition( PropertyDescriptor propertyDescriptor, object selectedObject, bool isPropertyGridCategorized )
: base( isPropertyGridCategorized )
{
this.Init( propertyDescriptor, selectedObject );
}
#endregion
#region Custom Properties
internal override PropertyDescriptor PropertyDescriptor
{
get
{
return _propertyDescriptor;
}
}
private object SelectedObject
{
get
{
return _selectedObject;
}
}
#endregion
#region Override Methods
internal override ObjectContainerHelperBase CreateContainerHelper( IPropertyContainer parent )
{
return new ObjectContainerHelper( parent, this.Value );
}
internal override void OnValueChanged( object oldValue, object newValue )
{
base.OnValueChanged( oldValue, newValue );
this.RaiseContainerHelperInvalidated();
}
protected override BindingBase CreateValueBinding()
{
var selectedObject = this.SelectedObject;
var propertyName = this.PropertyDescriptor.Name;
//Bind the value property with the source object.
var binding = new Binding( propertyName )
{
Source = this.GetValueInstance( selectedObject ),
Mode = PropertyDescriptor.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay,
ValidatesOnDataErrors = true,
ValidatesOnExceptions = true,
ConverterCulture = CultureInfo.CurrentCulture
};
return binding;
}
protected override bool ComputeIsReadOnly()
{
return PropertyDescriptor.IsReadOnly;
}
internal override ITypeEditor CreateDefaultEditor( PropertyItem propertyItem )
{
return PropertyGridUtilities.CreateDefaultEditor( PropertyDescriptor.PropertyType, PropertyDescriptor.Converter, propertyItem );
}
protected override bool ComputeCanResetValue()
{
return PropertyDescriptor.CanResetValue( SelectedObject )
&& !PropertyDescriptor.IsReadOnly;
}
protected override object ComputeAdvancedOptionsTooltip()
{
object tooltip;
UpdateAdvanceOptionsForItem( _markupObject, SelectedObject as DependencyObject, _dpDescriptor, out tooltip );
return tooltip;
}
protected override string ComputeCategory()
{
#if VS2008
return PropertyDescriptor.Category;
#else
var displayAttribute = PropertyGridUtilities.GetAttribute<DisplayAttribute>( PropertyDescriptor );
return ( (displayAttribute != null) && (displayAttribute.GetGroupName() != null) ) ? displayAttribute.GetGroupName() : PropertyDescriptor.Category;
#endif
}
protected override string ComputeCategoryValue()
{
return PropertyDescriptor.Category;
}
protected override bool ComputeExpandableAttribute()
{
return ( bool )this.ComputeExpandableAttributeForItem( PropertyDescriptor );
}
protected override bool ComputeIsExpandable()
{
return ( this.Value != null )
;
}
protected override IList<Type> ComputeNewItemTypes()
{
return ( IList<Type> )ComputeNewItemTypesForItem( PropertyDescriptor );
}
protected override string ComputeDescription()
{
return ( string )ComputeDescriptionForItem( PropertyDescriptor );
}
protected override int ComputeDisplayOrder( bool isPropertyGridCategorized )
{
this.IsPropertyGridCategorized = isPropertyGridCategorized;
return ( int )ComputeDisplayOrderForItem( PropertyDescriptor );
}
protected override void ResetValue()
{
PropertyDescriptor.ResetValue( SelectedObject );
}
internal override ITypeEditor CreateAttributeEditor()
{
var editorAttribute = GetAttribute<EditorAttribute>();
if( editorAttribute != null )
{
Type type = Type.GetType( editorAttribute.EditorTypeName );
// If the editor does not have any public parameterless constructor, forget it.
if( typeof( ITypeEditor ).IsAssignableFrom( type )
&& ( type.GetConstructor( new Type[ 0 ] ) != null ) )
{
var instance = Activator.CreateInstance( type ) as ITypeEditor;
Debug.Assert( instance != null, "Type was expected to be ITypeEditor with public constructor." );
if( instance != null )
return instance;
}
}
var itemsSourceAttribute = GetAttribute<ItemsSourceAttribute>();
if( itemsSourceAttribute != null )
return new ItemsSourceAttributeEditor( itemsSourceAttribute );
return null;
}
#endregion
#region Private Methods
private T GetAttribute<T>() where T : Attribute
{
return PropertyGridUtilities.GetAttribute<T>( PropertyDescriptor );
}
private void Init( PropertyDescriptor propertyDescriptor, object selectedObject )
{
if( propertyDescriptor == null )
throw new ArgumentNullException( "propertyDescriptor" );
if( selectedObject == null )
throw new ArgumentNullException( "selectedObject" );
_propertyDescriptor = propertyDescriptor;
_selectedObject = selectedObject;
_dpDescriptor = DependencyPropertyDescriptor.FromProperty( propertyDescriptor );
_markupObject = MarkupWriter.GetMarkupObjectFor( SelectedObject );
}
#endregion //Private Methods
}
}

View File

@@ -0,0 +1,614 @@
/*************************************************************************************
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;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.PropertyGrid.Commands;
using System.Windows.Media;
using System.Collections;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows.Markup.Primitives;
using System.Windows.Data;
using System.Windows.Media.Imaging;
#if !VS2008
using System.ComponentModel.DataAnnotations;
#endif
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal abstract class DescriptorPropertyDefinitionBase : DependencyObject
{
#region Members
private string _category;
private string _categoryValue;
private string _description;
private string _displayName;
private int _displayOrder;
private bool _expandableAttribute;
private bool _isReadOnly;
private IList<Type> _newItemTypes;
private IEnumerable<CommandBinding> _commandBindings;
#endregion
internal abstract PropertyDescriptor PropertyDescriptor
{
get;
}
#region Initialization
internal DescriptorPropertyDefinitionBase( bool isPropertyGridCategorized )
{
this.IsPropertyGridCategorized = isPropertyGridCategorized;
}
#endregion
#region Virtual Methods
protected virtual string ComputeCategory()
{
return null;
}
protected virtual string ComputeCategoryValue()
{
return null;
}
protected virtual string ComputeDescription()
{
return null;
}
protected virtual int ComputeDisplayOrder( bool isPropertyGridCategorized )
{
return int.MaxValue;
}
protected virtual bool ComputeExpandableAttribute()
{
return false;
}
protected abstract bool ComputeIsExpandable();
protected virtual IList<Type> ComputeNewItemTypes()
{
return null;
}
protected virtual bool ComputeIsReadOnly()
{
return false;
}
protected virtual bool ComputeCanResetValue()
{
return false;
}
protected virtual object ComputeAdvancedOptionsTooltip()
{
return null;
}
protected virtual void ResetValue()
{
}
protected abstract BindingBase CreateValueBinding();
#endregion
#region Internal Methods
internal abstract ObjectContainerHelperBase CreateContainerHelper( IPropertyContainer parent );
internal void RaiseContainerHelperInvalidated()
{
if( this.ContainerHelperInvalidated != null )
{
this.ContainerHelperInvalidated( this, EventArgs.Empty );
}
}
internal virtual ITypeEditor CreateDefaultEditor( PropertyItem propertyItem )
{
return null;
}
internal virtual ITypeEditor CreateAttributeEditor()
{
return null;
}
internal void UpdateAdvanceOptionsForItem( MarkupObject markupObject, DependencyObject dependencyObject, DependencyPropertyDescriptor dpDescriptor,
out object tooltip )
{
tooltip = StringConstants.AdvancedProperties;
bool isResource = false;
bool isDynamicResource = false;
var markupProperty = markupObject.Properties.FirstOrDefault( p => p.Name == PropertyName );
if( markupProperty != null )
{
//TODO: need to find a better way to determine if a StaticResource has been applied to any property not just a style(maybe with StaticResourceExtension)
isResource = typeof( Style ).IsAssignableFrom( markupProperty.PropertyType );
isDynamicResource = typeof( DynamicResourceExtension ).IsAssignableFrom( markupProperty.PropertyType );
}
if( isResource || isDynamicResource )
{
tooltip = StringConstants.Resource;
}
else
{
if( (dependencyObject != null) && (dpDescriptor != null) )
{
if( BindingOperations.GetBindingExpressionBase( dependencyObject, dpDescriptor.DependencyProperty ) != null )
{
tooltip = StringConstants.Databinding;
}
else
{
BaseValueSource bvs =
DependencyPropertyHelper
.GetValueSource( dependencyObject, dpDescriptor.DependencyProperty )
.BaseValueSource;
switch( bvs )
{
case BaseValueSource.Inherited:
case BaseValueSource.DefaultStyle:
case BaseValueSource.ImplicitStyleReference:
tooltip = StringConstants.Inheritance;
break;
case BaseValueSource.DefaultStyleTrigger:
break;
case BaseValueSource.Style:
tooltip = StringConstants.StyleSetter;
break;
case BaseValueSource.Local:
tooltip = StringConstants.Local;
break;
}
}
}
}
}
internal void UpdateAdvanceOptions()
{
// Only set the Tooltip. the Icon will be added in XAML based on the Tooltip.
this.AdvancedOptionsTooltip = this.ComputeAdvancedOptionsTooltip();
}
internal void UpdateIsExpandable()
{
this.IsExpandable =
this.ExpandableAttribute
&& this.ComputeIsExpandable();
}
internal void UpdateValueFromSource()
{
BindingOperations.GetBindingExpressionBase( this, DescriptorPropertyDefinitionBase.ValueProperty ).UpdateTarget();
}
internal object ComputeDescriptionForItem( object item )
{
PropertyDescriptor pd = item as PropertyDescriptor;
//We do not simply rely on the "Description" property of PropertyDescriptor
//since this value is cached by PropertyDescriptor and the localized version
//(e.g., LocalizedDescriptionAttribute) value can dynamicaly change.
#if !VS2008
var displayAttribute = PropertyGridUtilities.GetAttribute<DisplayAttribute>( pd );
if( displayAttribute != null )
{
return displayAttribute.GetDescription();
}
#endif
var descriptionAtt = PropertyGridUtilities.GetAttribute<DescriptionAttribute>( pd );
return (descriptionAtt != null)
? descriptionAtt.Description
: pd.Description;
}
internal object ComputeNewItemTypesForItem( object item )
{
PropertyDescriptor pd = item as PropertyDescriptor;
var attribute = PropertyGridUtilities.GetAttribute<NewItemTypesAttribute>( pd );
return (attribute != null)
? attribute.Types
: null;
}
internal object ComputeDisplayOrderForItem( object item )
{
PropertyDescriptor pd = item as PropertyDescriptor;
#if !VS2008
var displayAttribute = PropertyGridUtilities.GetAttribute<DisplayAttribute>( PropertyDescriptor );
if( displayAttribute != null )
{
var order = displayAttribute.GetOrder();
if( order.HasValue )
return displayAttribute.GetOrder();
}
#endif
List<PropertyOrderAttribute> list = pd.Attributes.OfType<PropertyOrderAttribute>().ToList();
if( list.Count > 0 )
{
this.ValidatePropertyOrderAttributes( list );
if( this.IsPropertyGridCategorized )
{
var attribute = list.FirstOrDefault( x => ((x.UsageContext == UsageContextEnum.Categorized)
|| (x.UsageContext == UsageContextEnum.Both)) );
if( attribute != null )
return attribute.Order;
}
else
{
var attribute = list.FirstOrDefault( x => ((x.UsageContext == UsageContextEnum.Alphabetical)
|| (x.UsageContext == UsageContextEnum.Both)) );
if( attribute != null )
return attribute.Order;
}
}
// Max Value. Properties with no order will be displayed last.
return int.MaxValue;
}
internal object ComputeExpandableAttributeForItem( object item )
{
var pd = (PropertyDescriptor)item;
var attribute = PropertyGridUtilities.GetAttribute<ExpandableObjectAttribute>( pd );
return (attribute != null);
}
internal int ComputeDisplayOrderInternal( bool isPropertyGridCategorized )
{
return this.ComputeDisplayOrder( isPropertyGridCategorized );
}
internal object GetValueInstance( object sourceObject )
{
ICustomTypeDescriptor customTypeDescriptor = sourceObject as ICustomTypeDescriptor;
if( customTypeDescriptor != null )
sourceObject = customTypeDescriptor.GetPropertyOwner( PropertyDescriptor );
return sourceObject;
}
#endregion
#region Private Methods
private void ExecuteResetValueCommand( object sender, ExecutedRoutedEventArgs e )
{
if( ComputeCanResetValue() )
ResetValue();
}
private void CanExecuteResetValueCommand( object sender, CanExecuteRoutedEventArgs e )
{
e.CanExecute = ComputeCanResetValue();
}
private string ComputeDisplayName()
{
#if VS2008
var displayName = PropertyDescriptor.DisplayName;
#else
var displayAttribute = PropertyGridUtilities.GetAttribute<DisplayAttribute>( PropertyDescriptor );
var displayName = (displayAttribute != null) ? displayAttribute.GetName() : PropertyDescriptor.DisplayName;
#endif
var attribute = PropertyGridUtilities.GetAttribute<ParenthesizePropertyNameAttribute>( PropertyDescriptor );
if( (attribute != null) && attribute.NeedParenthesis )
{
displayName = "(" + displayName + ")";
}
return displayName;
}
private void ValidatePropertyOrderAttributes( List<PropertyOrderAttribute> list )
{
if( list.Count > 0 )
{
PropertyOrderAttribute both = list.FirstOrDefault( x => x.UsageContext == UsageContextEnum.Both );
if( (both != null) && (list.Count > 1) )
Debug.Assert( false, "A PropertyItem can't have more than 1 PropertyOrderAttribute when it has UsageContext : Both" );
}
}
#endregion
#region Events
public event EventHandler ContainerHelperInvalidated;
#endregion
#region AdvancedOptionsIcon (DP)
public static readonly DependencyProperty AdvancedOptionsIconProperty =
DependencyProperty.Register( "AdvancedOptionsIcon", typeof( ImageSource ), typeof( DescriptorPropertyDefinitionBase ), new UIPropertyMetadata( null ) );
public ImageSource AdvancedOptionsIcon
{
get
{
return (ImageSource)GetValue( AdvancedOptionsIconProperty );
}
set
{
SetValue( AdvancedOptionsIconProperty, value );
}
}
#endregion
#region AdvancedOptionsTooltip (DP)
public static readonly DependencyProperty AdvancedOptionsTooltipProperty =
DependencyProperty.Register( "AdvancedOptionsTooltip", typeof( object ), typeof( DescriptorPropertyDefinitionBase ), new UIPropertyMetadata( null ) );
public object AdvancedOptionsTooltip
{
get
{
return (object)GetValue( AdvancedOptionsTooltipProperty );
}
set
{
SetValue( AdvancedOptionsTooltipProperty, value );
}
}
#endregion //AdvancedOptionsTooltip
#region IsExpandable (DP)
public static readonly DependencyProperty IsExpandableProperty =
DependencyProperty.Register( "IsExpandable", typeof( bool ), typeof( DescriptorPropertyDefinitionBase ), new UIPropertyMetadata( false ) );
public bool IsExpandable
{
get
{
return (bool)GetValue( IsExpandableProperty );
}
set
{
SetValue( IsExpandableProperty, value );
}
}
#endregion //IsExpandable
public string Category
{
get
{
return _category;
}
internal set
{
_category = value;
}
}
public string CategoryValue
{
get
{
return _categoryValue;
}
internal set
{
_categoryValue = value;
}
}
public IEnumerable<CommandBinding> CommandBindings
{
get
{
return _commandBindings;
}
}
public string DisplayName
{
get
{
return _displayName;
}
internal set
{
_displayName = value;
}
}
public string Description
{
get
{
return _description;
}
internal set
{
_description = value;
}
}
public int DisplayOrder
{
get
{
return _displayOrder;
}
internal set
{
_displayOrder = value;
}
}
public bool IsReadOnly
{
get
{
return _isReadOnly;
}
}
public IList<Type> NewItemTypes
{
get
{
return _newItemTypes;
}
}
public string PropertyName
{
get
{
// A common property which is present in all selectedObjects will always have the same name.
return PropertyDescriptor.Name;
}
}
public Type PropertyType
{
get
{
return PropertyDescriptor.PropertyType;
}
}
internal bool ExpandableAttribute
{
get
{
return _expandableAttribute;
}
set
{
_expandableAttribute = value;
this.UpdateIsExpandable();
}
}
internal bool IsPropertyGridCategorized
{
get;
set;
}
#region Value Property (DP)
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( object ), typeof( DescriptorPropertyDefinitionBase ), new UIPropertyMetadata( null, OnValueChanged ) );
public object Value
{
get
{
return GetValue( ValueProperty );
}
set
{
SetValue( ValueProperty, value );
}
}
private static void OnValueChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
((DescriptorPropertyDefinitionBase)o).OnValueChanged( e.OldValue, e.NewValue );
}
internal virtual void OnValueChanged( object oldValue, object newValue )
{
UpdateIsExpandable();
UpdateAdvanceOptions();
// Reset command also affected.
CommandManager.InvalidateRequerySuggested();
}
#endregion //Value Property
public virtual void InitProperties()
{
// Do "IsReadOnly" and PropertyName first since the others may need that value.
_isReadOnly = ComputeIsReadOnly();
_category = ComputeCategory();
_categoryValue = ComputeCategoryValue();
_description = ComputeDescription();
_displayName = ComputeDisplayName();
_displayOrder = ComputeDisplayOrder( this.IsPropertyGridCategorized );
_expandableAttribute = ComputeExpandableAttribute();
_newItemTypes = ComputeNewItemTypes();
_commandBindings = new CommandBinding[] { new CommandBinding( PropertyItemCommands.ResetValue, ExecuteResetValueCommand, CanExecuteResetValueCommand ) };
UpdateIsExpandable();
UpdateAdvanceOptions();
BindingBase valueBinding = this.CreateValueBinding();
BindingOperations.SetBinding( this, DescriptorPropertyDefinitionBase.ValueProperty, valueBinding );
}
}
}

View File

@@ -0,0 +1,100 @@
/*************************************************************************************
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.Windows;
using System.Collections.Generic;
using System.Linq;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
[Obsolete(@"Use EditorTemplateDefinition instead of EditorDefinition. " + EditorDefinition.UsageEx)]
public class EditorDefinition : EditorTemplateDefinition
{
private const string UsageEx = " (XAML Ex: <t:EditorTemplateDefinition TargetProperties=\"FirstName,LastName\" .../> OR <t:EditorTemplateDefinition TargetProperties=\"{x:Type l:MyType}\" .../> )";
public EditorDefinition()
{
const string usageErr = "{0} is obsolete. Instead use {1}.";
System.Diagnostics.Trace.TraceWarning( string.Format( usageErr, typeof( EditorDefinition ), typeof( EditorTemplateDefinition ) ) + UsageEx );
}
/// <summary>
/// Gets or sets the template of the editor.
/// This Property is part of the obsolete EditorDefinition class.
/// Use EditorTemplateDefinition class and the Edit<b>ing</b>Template property.
/// </summary>
public DataTemplate EditorTemplate
{
get;
set;
}
private PropertyDefinitionCollection _properties = new PropertyDefinitionCollection();
/// <summary>
/// List the PropertyDefinitions that identify the properties targeted by the EditorTemplate.
/// This Property is part of the obsolete EditorDefinition class.
/// Use "EditorTemplateDefinition" class and the "TargetProperties" property<br/>
/// XAML Ex.: &lt;t:EditorTemplateDefinition TargetProperties="FirstName,LastName" .../&gt;
/// </summary>
public PropertyDefinitionCollection PropertiesDefinitions
{
get
{
return _properties;
}
set
{
_properties = value;
}
}
public Type TargetType
{
get;
set;
}
internal override void Lock()
{
const string usageError = @"Use a EditorTemplateDefinition instead of EditorDefinition in order to use the '{0}' property.";
if( this.EditingTemplate != null )
throw new InvalidOperationException( string.Format( usageError, "EditingTemplate" ) );
if( this.TargetProperties != null && this.TargetProperties.Count > 0)
throw new InvalidOperationException( string.Format( usageError, "TargetProperties" ) );
List<object> properties = new List<object>();
if( this.PropertiesDefinitions != null )
{
foreach( PropertyDefinition def in this.PropertiesDefinitions )
{
if( def.TargetProperties != null )
{
properties.AddRange( def.TargetProperties.Cast<object>() );
}
}
}
this.TargetProperties = properties;
this.EditingTemplate = this.EditorTemplate;
base.Lock();
}
}
}

View File

@@ -0,0 +1,47 @@
/*************************************************************************************
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.Windows;
using System.Windows.Controls;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class CheckBoxEditor : TypeEditor<CheckBox>
{
protected override CheckBox CreateEditor()
{
return new PropertyGridEditorCheckBox();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
Editor.Margin = new Thickness( 5, 0, 0, 0 );
}
protected override void SetValueDependencyProperty()
{
ValueProperty = CheckBox.IsCheckedProperty;
}
}
public class PropertyGridEditorCheckBox : CheckBox
{
static PropertyGridEditorCheckBox()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorCheckBox ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorCheckBox ) ) );
}
}
}

View File

@@ -0,0 +1,97 @@
/*************************************************************************************
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.Linq;
using System.Windows;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class CollectionEditor : TypeEditor<CollectionControlButton>
{
protected override void SetValueDependencyProperty()
{
ValueProperty = CollectionControlButton.ItemsSourceProperty;
}
protected override void ResolveValueBinding( PropertyItem propertyItem )
{
var type = propertyItem.PropertyType;
Editor.ItemsSourceType = type;
if( type.BaseType == typeof( System.Array ) )
{
Editor.NewItemTypes = new List<Type>() { type.GetElementType() };
}
else
{
if( (propertyItem.DescriptorDefinition != null)
&& (propertyItem.DescriptorDefinition.NewItemTypes != null)
&& (propertyItem.DescriptorDefinition.NewItemTypes.Count > 0) )
{
Editor.NewItemTypes = propertyItem.DescriptorDefinition.NewItemTypes;
}
else
{
//Check if we have a Dictionary
var dictionaryTypes = ListUtilities.GetDictionaryItemsType( type );
if( (dictionaryTypes != null) && (dictionaryTypes.Length == 2) )
{
// A Dictionary contains KeyValuePair that can't be edited.
// We need to create EditableKeyValuePairs.
// Create a EditableKeyValuePair< TKey, TValue> type from dictionary generic arguments type
var editableKeyValuePairType = ListUtilities.CreateEditableKeyValuePairType( dictionaryTypes[ 0 ], dictionaryTypes[ 1 ] );
Editor.NewItemTypes = new List<Type>() { editableKeyValuePairType };
}
else
{
//Check if we have a list
var listType = ListUtilities.GetListItemType( type );
if( listType != null )
{
Editor.NewItemTypes = new List<Type>() { listType };
}
else
{
//Check if we have a Collection of T
var colType = ListUtilities.GetCollectionItemType( type );
if( colType != null )
{
Editor.NewItemTypes = new List<Type>() { colType };
}
}
}
}
}
base.ResolveValueBinding( propertyItem );
}
}
public class PropertyGridEditorCollectionControl : CollectionControlButton
{
static PropertyGridEditorCollectionControl()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorCollectionControl ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorCollectionControl ) ) );
}
}
}

View File

@@ -0,0 +1,45 @@
/*************************************************************************************
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.Windows;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class ColorEditor : TypeEditor<ColorPicker>
{
protected override ColorPicker CreateEditor()
{
return new PropertyGridEditorColorPicker();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
Editor.BorderThickness = new System.Windows.Thickness( 0 );
Editor.DisplayColorAndName = true;
}
protected override void SetValueDependencyProperty()
{
ValueProperty = ColorPicker.SelectedColorProperty;
}
}
public class PropertyGridEditorColorPicker : ColorPicker
{
static PropertyGridEditorColorPicker()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorColorPicker ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorColorPicker ) ) );
}
}
}

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.Collections.Generic;
using System.Collections;
using System.Windows;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public abstract class ComboBoxEditor : TypeEditor<System.Windows.Controls.ComboBox>
{
protected override void SetValueDependencyProperty()
{
ValueProperty = System.Windows.Controls.ComboBox.SelectedItemProperty;
}
protected override System.Windows.Controls.ComboBox CreateEditor()
{
return new PropertyGridEditorComboBox();
}
protected override void ResolveValueBinding( PropertyItem propertyItem )
{
SetItemsSource( propertyItem );
base.ResolveValueBinding( propertyItem );
}
protected abstract IEnumerable CreateItemsSource( PropertyItem propertyItem );
private void SetItemsSource( PropertyItem propertyItem )
{
Editor.ItemsSource = CreateItemsSource( propertyItem );
}
}
public class PropertyGridEditorComboBox : System.Windows.Controls.ComboBox
{
static PropertyGridEditorComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorComboBox ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorComboBox ) ) );
}
}
}

View File

@@ -0,0 +1,59 @@
/*************************************************************************************
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.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Collections;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class EnumComboBoxEditor : ComboBoxEditor
{
protected override IEnumerable CreateItemsSource( PropertyItem propertyItem )
{
return GetValues( propertyItem.PropertyType );
}
private static object[] GetValues( Type enumType )
{
List<object> values = new List<object>();
if( enumType != null )
{
var fields = enumType.GetFields().Where( x => x.IsLiteral );
foreach( FieldInfo field in fields )
{
// Get array of BrowsableAttribute attributes
object[] attrs = field.GetCustomAttributes( typeof( BrowsableAttribute ), false );
if( attrs.Length == 1 )
{
// If attribute exists and its value is false continue to the next field...
BrowsableAttribute brAttr = ( BrowsableAttribute )attrs[ 0 ];
if( brAttr.Browsable == false )
continue;
}
values.Add( field.GetValue( enumType ) );
}
}
return values.ToArray();
}
}
}

View File

@@ -0,0 +1,42 @@
/*************************************************************************************
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.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Collections;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class FontComboBoxEditor : ComboBoxEditor
{
protected override IEnumerable CreateItemsSource( PropertyItem propertyItem )
{
if( propertyItem.PropertyType == typeof( FontFamily ) )
return FontUtilities.Families.OrderBy( x => x.Source);
else if( propertyItem.PropertyType == typeof( FontWeight ) )
return FontUtilities.Weights;
else if( propertyItem.PropertyType == typeof( FontStyle ) )
return FontUtilities.Styles;
else if( propertyItem.PropertyType == typeof( FontStretch ) )
return FontUtilities.Stretches;
return null;
}
}
}

View File

@@ -0,0 +1,25 @@
/*************************************************************************************
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.Windows;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public interface ITypeEditor
{
FrameworkElement ResolveEditor( PropertyItem propertyItem );
}
}

View File

@@ -0,0 +1,64 @@
/*************************************************************************************
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 Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class ItemsSourceAttributeEditor : TypeEditor<System.Windows.Controls.ComboBox>
{
private readonly ItemsSourceAttribute _attribute;
public ItemsSourceAttributeEditor( ItemsSourceAttribute attribute )
{
_attribute = attribute;
}
protected override void SetValueDependencyProperty()
{
ValueProperty = System.Windows.Controls.ComboBox.SelectedValueProperty;
}
protected override System.Windows.Controls.ComboBox CreateEditor()
{
return new PropertyGridEditorComboBox();
}
protected override void ResolveValueBinding( PropertyItem propertyItem )
{
SetItemsSource();
base.ResolveValueBinding( propertyItem );
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
Editor.DisplayMemberPath = "DisplayName";
Editor.SelectedValuePath = "Value";
}
private void SetItemsSource()
{
Editor.ItemsSource = CreateItemsSource();
}
private System.Collections.IEnumerable CreateItemsSource()
{
var instance = Activator.CreateInstance( _attribute.Type );
return ( instance as IItemsSource ).GetValues();
}
}
}

View File

@@ -0,0 +1,50 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class MaskedTextBoxEditor : TypeEditor<MaskedTextBox>
{
public string Mask
{
get;
set;
}
public Type ValueDataType
{
get;
set;
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
Editor.BorderThickness = new System.Windows.Thickness( 0 );
this.Editor.ValueDataType = this.ValueDataType;
this.Editor.Mask = this.Mask;
}
protected override void SetValueDependencyProperty()
{
this.ValueProperty = MaskedTextBox.ValueProperty;
}
}
}

View File

@@ -0,0 +1,63 @@
/*************************************************************************************
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.Windows;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class PrimitiveTypeCollectionEditor : TypeEditor<PrimitiveTypeCollectionControl>
{
protected override void SetControlProperties( PropertyItem propertyItem )
{
Editor.BorderThickness = new System.Windows.Thickness( 0 );
Editor.Content = "(Collection)";
}
protected override void SetValueDependencyProperty()
{
ValueProperty = PrimitiveTypeCollectionControl.ItemsSourceProperty;
}
protected override void ResolveValueBinding( PropertyItem propertyItem )
{
var type = propertyItem.PropertyType;
Editor.ItemsSourceType = type;
if( type.BaseType == typeof( System.Array ) )
{
Editor.ItemType = type.GetElementType();
}
else
{
var typeArguments = type.GetGenericArguments();
if( typeArguments.Length > 0 )
{
Editor.ItemType = typeArguments[ 0 ];
}
}
base.ResolveValueBinding( propertyItem );
}
}
public class PropertyGridEditorPrimitiveTypeCollectionControl : PrimitiveTypeCollectionControl
{
static PropertyGridEditorPrimitiveTypeCollectionControl()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorPrimitiveTypeCollectionControl ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorPrimitiveTypeCollectionControl ) ) );
}
}
}

View File

@@ -0,0 +1,79 @@
/*************************************************************************************
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.ComponentModel;
using System.Globalization;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class SourceComboBoxEditor : ComboBoxEditor
{
ICollection _collection;
TypeConverter _typeConverter;
public SourceComboBoxEditor( ICollection collection, TypeConverter typeConverter )
{
_collection = collection;
_typeConverter = typeConverter;
}
protected override IEnumerable CreateItemsSource( PropertyItem propertyItem )
{
return _collection;
}
protected override IValueConverter CreateValueConverter()
{
//When using a stringConverter, we need to convert the value
if( (_typeConverter != null) && (_typeConverter is StringConverter) )
return new SourceComboBoxEditorConverter( _typeConverter );
return null;
}
}
internal class SourceComboBoxEditorConverter : IValueConverter
{
private TypeConverter _typeConverter;
internal SourceComboBoxEditorConverter( TypeConverter typeConverter )
{
_typeConverter = typeConverter;
}
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( _typeConverter != null )
{
if( _typeConverter.CanConvertTo( typeof(string) ) )
return _typeConverter.ConvertTo( value, typeof(string) );
}
return value;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
if( _typeConverter != null )
{
if( _typeConverter.CanConvertFrom( value.GetType() ) )
return _typeConverter.ConvertFrom( value );
}
return value;
}
}
}

View File

@@ -0,0 +1,47 @@
/*************************************************************************************
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.Windows.Controls;
using System.Windows;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class TextBlockEditor : TypeEditor<TextBlock>
{
protected override TextBlock CreateEditor()
{
return new PropertyGridEditorTextBlock();
}
protected override void SetValueDependencyProperty()
{
ValueProperty = TextBlock.TextProperty;
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
Editor.Margin = new System.Windows.Thickness( 5, 0, 0, 0 );
}
}
public class PropertyGridEditorTextBlock : TextBlock
{
static PropertyGridEditorTextBlock()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorTextBlock ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorTextBlock ) ) );
}
}
}

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.Windows.Controls;
using System.Windows;
#if !VS2008
using System.ComponentModel.DataAnnotations;
#endif
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class TextBoxEditor : TypeEditor<WatermarkTextBox>
{
protected override WatermarkTextBox CreateEditor()
{
return new PropertyGridEditorTextBox();
}
#if !VS2008
protected override void SetControlProperties( PropertyItem propertyItem )
{
var displayAttribute = PropertyGridUtilities.GetAttribute<DisplayAttribute>( propertyItem.PropertyDescriptor );
if( displayAttribute != null )
{
this.Editor.Watermark = displayAttribute.GetPrompt();
}
}
#endif
protected override void SetValueDependencyProperty()
{
ValueProperty = TextBox.TextProperty;
}
}
public class PropertyGridEditorTextBox : WatermarkTextBox
{
static PropertyGridEditorTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorTextBox ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorTextBox ) ) );
}
}
}

View File

@@ -0,0 +1,84 @@
/*************************************************************************************
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.Windows;
using System.Windows.Data;
using Xceed.Wpf.Toolkit.Primitives;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public abstract class TypeEditor<T> : ITypeEditor where T : FrameworkElement, new()
{
#region Properties
protected T Editor
{
get;
set;
}
protected DependencyProperty ValueProperty
{
get;
set;
}
#endregion //Properties
#region ITypeEditor Members
public virtual FrameworkElement ResolveEditor( PropertyItem propertyItem )
{
Editor = this.CreateEditor();
SetValueDependencyProperty();
SetControlProperties( propertyItem );
ResolveValueBinding( propertyItem );
return Editor;
}
#endregion //ITypeEditor Members
#region Methods
protected virtual T CreateEditor()
{
return new T();
}
protected virtual IValueConverter CreateValueConverter()
{
return null;
}
protected virtual void ResolveValueBinding( PropertyItem propertyItem )
{
var _binding = new Binding( "Value" );
_binding.Source = propertyItem;
_binding.UpdateSourceTrigger = (Editor is InputBase) ? UpdateSourceTrigger.PropertyChanged : UpdateSourceTrigger.Default;
_binding.Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay;
_binding.Converter = CreateValueConverter();
BindingOperations.SetBinding( Editor, ValueProperty, _binding );
}
protected virtual void SetControlProperties( PropertyItem propertyItem )
{
//TODO: implement in derived class
}
protected abstract void SetValueDependencyProperty();
#endregion //Methods
}
}

View File

@@ -0,0 +1,369 @@
/*************************************************************************************
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 Xceed.Wpf.Toolkit.Primitives;
using System;
using System.Windows;
#if !VS2008
using System.ComponentModel.DataAnnotations;
#endif
using System.ComponentModel;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class UpDownEditor<TEditor, TType> : TypeEditor<TEditor> where TEditor : UpDownBase<TType>, new()
{
protected override void SetControlProperties( PropertyItem propertyItem )
{
Editor.TextAlignment = System.Windows.TextAlignment.Left;
}
protected override void SetValueDependencyProperty()
{
ValueProperty = UpDownBase<TType>.ValueProperty;
}
#if !VS2008
internal void SetMinMaxFromRangeAttribute( PropertyDescriptor propertyDescriptor, TypeConverter converter )
{
if( propertyDescriptor == null )
return;
var rangeAttribute = PropertyGridUtilities.GetAttribute<RangeAttribute>( propertyDescriptor );
if( rangeAttribute != null )
{
Editor.Maximum = ((TType)converter.ConvertFrom( rangeAttribute.Maximum.ToString() ));
Editor.Minimum = ((TType)converter.ConvertFrom( rangeAttribute.Minimum.ToString() ));
}
}
#endif
}
public class ByteUpDownEditor : UpDownEditor<ByteUpDown, byte?>
{
protected override ByteUpDown CreateEditor()
{
return new PropertyGridEditorByteUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( byte ) ) );
#endif
}
}
public class DecimalUpDownEditor : UpDownEditor<DecimalUpDown, decimal?>
{
protected override DecimalUpDown CreateEditor()
{
return new PropertyGridEditorDecimalUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( decimal ) ) );
#endif
}
}
public class DoubleUpDownEditor : UpDownEditor<DoubleUpDown, double?>
{
protected override DoubleUpDown CreateEditor()
{
return new PropertyGridEditorDoubleUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
Editor.AllowInputSpecialValues = AllowedSpecialValues.Any;
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( double ) ) );
#endif
}
}
public class IntegerUpDownEditor : UpDownEditor<IntegerUpDown, int?>
{
protected override IntegerUpDown CreateEditor()
{
return new PropertyGridEditorIntegerUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( int ) ) );
#endif
}
}
public class LongUpDownEditor : UpDownEditor<LongUpDown, long?>
{
protected override LongUpDown CreateEditor()
{
return new PropertyGridEditorLongUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( long ) ) );
#endif
}
}
public class ShortUpDownEditor : UpDownEditor<ShortUpDown, short?>
{
protected override ShortUpDown CreateEditor()
{
return new PropertyGridEditorShortUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( short ) ) );
#endif
}
}
public class SingleUpDownEditor : UpDownEditor<SingleUpDown, float?>
{
protected override SingleUpDown CreateEditor()
{
return new PropertyGridEditorSingleUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
Editor.AllowInputSpecialValues = AllowedSpecialValues.Any;
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( float ) ) );
#endif
}
}
public class DateTimeUpDownEditor : UpDownEditor<DateTimeUpDown, DateTime?>
{
protected override DateTimeUpDown CreateEditor()
{
return new PropertyGridEditorDateTimeUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( DateTime ) ) );
#endif
}
}
public class TimeSpanUpDownEditor : UpDownEditor<TimeSpanUpDown, TimeSpan?>
{
protected override TimeSpanUpDown CreateEditor()
{
return new PropertyGridEditorTimeSpanUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( TimeSpan ) ) );
#endif
}
}
internal class SByteUpDownEditor : UpDownEditor<SByteUpDown, sbyte?>
{
protected override SByteUpDown CreateEditor()
{
return new PropertyGridEditorSByteUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( sbyte ) ) );
#endif
}
}
internal class UIntegerUpDownEditor : UpDownEditor<UIntegerUpDown, uint?>
{
protected override UIntegerUpDown CreateEditor()
{
return new PropertyGridEditorUIntegerUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( uint ) ) );
#endif
}
}
internal class ULongUpDownEditor : UpDownEditor<ULongUpDown, ulong?>
{
protected override ULongUpDown CreateEditor()
{
return new PropertyGridEditorULongUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( ulong ) ) );
#endif
}
}
internal class UShortUpDownEditor : UpDownEditor<UShortUpDown, ushort?>
{
protected override UShortUpDown CreateEditor()
{
return new PropertyGridEditorUShortUpDown();
}
protected override void SetControlProperties( PropertyItem propertyItem )
{
base.SetControlProperties( propertyItem );
#if !VS2008
this.SetMinMaxFromRangeAttribute( propertyItem.PropertyDescriptor, TypeDescriptor.GetConverter( typeof( ushort ) ) );
#endif
}
}
public class PropertyGridEditorByteUpDown : ByteUpDown
{
static PropertyGridEditorByteUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorByteUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorByteUpDown ) ) );
}
}
public class PropertyGridEditorDecimalUpDown : DecimalUpDown
{
static PropertyGridEditorDecimalUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorDecimalUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorDecimalUpDown ) ) );
}
}
public class PropertyGridEditorDoubleUpDown : DoubleUpDown
{
static PropertyGridEditorDoubleUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorDoubleUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorDoubleUpDown ) ) );
}
}
public class PropertyGridEditorIntegerUpDown : IntegerUpDown
{
static PropertyGridEditorIntegerUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorIntegerUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorIntegerUpDown ) ) );
}
}
public class PropertyGridEditorLongUpDown : LongUpDown
{
static PropertyGridEditorLongUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorLongUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorLongUpDown ) ) );
}
}
public class PropertyGridEditorShortUpDown : ShortUpDown
{
static PropertyGridEditorShortUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorShortUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorShortUpDown ) ) );
}
}
public class PropertyGridEditorSingleUpDown : SingleUpDown
{
static PropertyGridEditorSingleUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorSingleUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorSingleUpDown ) ) );
}
}
public class PropertyGridEditorDateTimeUpDown : DateTimeUpDown
{
static PropertyGridEditorDateTimeUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorDateTimeUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorDateTimeUpDown ) ) );
}
}
public class PropertyGridEditorTimeSpanUpDown : TimeSpanUpDown
{
static PropertyGridEditorTimeSpanUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorTimeSpanUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorTimeSpanUpDown ) ) );
}
}
internal class PropertyGridEditorSByteUpDown : SByteUpDown
{
static PropertyGridEditorSByteUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorSByteUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorSByteUpDown ) ) );
}
}
internal class PropertyGridEditorUIntegerUpDown : UIntegerUpDown
{
static PropertyGridEditorUIntegerUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorUIntegerUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorUIntegerUpDown ) ) );
}
}
internal class PropertyGridEditorULongUpDown : ULongUpDown
{
static PropertyGridEditorULongUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorULongUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorULongUpDown ) ) );
}
}
internal class PropertyGridEditorUShortUpDown : UShortUpDown
{
static PropertyGridEditorUShortUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGridEditorUShortUpDown ), new FrameworkPropertyMetadata( typeof( PropertyGridEditorUShortUpDown ) ) );
}
}
}

View File

@@ -0,0 +1,29 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal struct FilterInfo
{
public string InputString;
public Predicate<object> Predicate;
}
}

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.Collections.Generic;
using System.Windows.Controls;
using System.Collections;
using System.ComponentModel;
using System.Windows.Data;
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal interface IPropertyContainer
{
ContainerHelperBase ContainerHelper { get; }
Style PropertyContainerStyle { get; }
EditorDefinitionCollection EditorDefinitions { get; }
PropertyDefinitionCollection PropertyDefinitions { get; }
bool IsCategorized { get; }
bool IsSortedAlphabetically { get; }
bool AutoGenerateProperties { get; }
bool HideInheritedProperties { get; }
FilterInfo FilterInfo { get; }
bool? IsPropertyVisible( PropertyDescriptor pd );
}
}

View File

@@ -0,0 +1,169 @@
/*************************************************************************************
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.ComponentModel;
#if !VS2008
using System.ComponentModel.DataAnnotations;
#endif
using System.Diagnostics;
using System.Linq;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal class ObjectContainerHelper : ObjectContainerHelperBase
{
private object _selectedObject;
public ObjectContainerHelper( IPropertyContainer propertyContainer, object selectedObject )
: base( propertyContainer )
{
_selectedObject = selectedObject;
}
private object SelectedObject
{
get
{
return _selectedObject;
}
}
protected override string GetDefaultPropertyName()
{
object selectedObject = SelectedObject;
return ( selectedObject != null ) ? ObjectContainerHelperBase.GetDefaultPropertyName( SelectedObject ) : ( string )null;
}
protected override IEnumerable<PropertyItem> GenerateSubPropertiesCore()
{
var propertyItems = new List<PropertyItem>();
if( SelectedObject != null )
{
try
{
List<PropertyDescriptor> descriptors = new List<PropertyDescriptor>();
{
descriptors = ObjectContainerHelperBase.GetPropertyDescriptors( SelectedObject, this.PropertyContainer.HideInheritedProperties );
}
foreach( var descriptor in descriptors )
{
var propertyDef = this.GetPropertyDefinition( descriptor );
bool isBrowsable = false;
var isPropertyBrowsable = this.PropertyContainer.IsPropertyVisible( descriptor );
if( isPropertyBrowsable.HasValue )
{
isBrowsable = isPropertyBrowsable.Value;
}
else
{
#if !VS2008
var displayAttribute = PropertyGridUtilities.GetAttribute<DisplayAttribute>( descriptor );
if( displayAttribute != null )
{
var autoGenerateField = displayAttribute.GetAutoGenerateField();
isBrowsable = this.PropertyContainer.AutoGenerateProperties
&& ((autoGenerateField.HasValue && autoGenerateField.Value) || !autoGenerateField.HasValue);
}
else
#endif
{
isBrowsable = descriptor.IsBrowsable && this.PropertyContainer.AutoGenerateProperties;
}
if( propertyDef != null )
{
isBrowsable = propertyDef.IsBrowsable.GetValueOrDefault( isBrowsable );
}
}
if( isBrowsable )
{
var prop = this.CreatePropertyItem( descriptor, propertyDef );
if( prop != null )
{
propertyItems.Add( prop );
}
}
}
}
catch( Exception e )
{
//TODO: handle this some how
Debug.WriteLine( "Property creation failed." );
Debug.WriteLine( e.StackTrace );
}
}
return propertyItems;
}
private PropertyItem CreatePropertyItem( PropertyDescriptor property, PropertyDefinition propertyDef )
{
DescriptorPropertyDefinition definition = new DescriptorPropertyDefinition( property,
SelectedObject,
this.PropertyContainer.IsCategorized
);
definition.InitProperties();
this.InitializeDescriptorDefinition( definition, propertyDef );
PropertyItem propertyItem = new PropertyItem( definition );
Debug.Assert( SelectedObject != null );
propertyItem.Instance = SelectedObject;
propertyItem.CategoryOrder = this.GetCategoryOrder( definition.CategoryValue );
propertyItem.WillRefreshPropertyGrid = this.GetWillRefreshPropertyGrid( property );
return propertyItem;
}
private int GetCategoryOrder( object categoryValue )
{
Debug.Assert( SelectedObject != null );
if( categoryValue == null )
return int.MaxValue;
int order = int.MaxValue;
object selectedObject = SelectedObject;
CategoryOrderAttribute[] orderAttributes = ( selectedObject != null )
? ( CategoryOrderAttribute[] )selectedObject.GetType().GetCustomAttributes( typeof( CategoryOrderAttribute ), true )
: new CategoryOrderAttribute[ 0 ];
var orderAttribute = orderAttributes
.FirstOrDefault( ( a ) => object.Equals( a.CategoryValue, categoryValue ) );
if( orderAttribute != null )
{
order = orderAttribute.Order;
}
return order;
}
}
}

View File

@@ -0,0 +1,540 @@
/*************************************************************************************
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.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.Core.Utilities;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
using System.Collections;
using System.Collections.ObjectModel;
using System.Windows.Controls.Primitives;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal abstract class ObjectContainerHelperBase : ContainerHelperBase
{
// This is needed to work around the ItemsControl behavior.
// When ItemsControl is preparing its containers, it appears
// that calling Refresh() on the CollectionView bound to
// the ItemsSource prevents the items from being displayed.
// This patch is to avoid such a behavior.
private bool _isPreparingItemFlag = false;
private PropertyItemCollection _propertyItemCollection;
public ObjectContainerHelperBase( IPropertyContainer propertyContainer)
: base( propertyContainer )
{
_propertyItemCollection = new PropertyItemCollection( new ObservableCollection<PropertyItem>() );
UpdateFilter();
UpdateCategorization( false );
}
public override IList Properties
{
get { return _propertyItemCollection; }
}
private PropertyItem DefaultProperty
{
get
{
PropertyItem defaultProperty = null;
var defaultName = this.GetDefaultPropertyName();
if( defaultName != null )
{
defaultProperty = _propertyItemCollection
.FirstOrDefault( ( prop ) => object.Equals( defaultName, prop.PropertyDescriptor.Name ) );
}
return defaultProperty;
}
}
protected PropertyItemCollection PropertyItems
{
get
{
return _propertyItemCollection;
}
}
public override PropertyItemBase ContainerFromItem( object item )
{
if( item == null )
return null;
// Exception case for ObjectContainerHelperBase. The "Item" may sometimes
// be identified as a string representing the property name or
// the PropertyItem itself.
Debug.Assert( item is PropertyItem || item is string );
var propertyItem = item as PropertyItem;
if( propertyItem != null )
return propertyItem;
var propertyStr = item as string;
if( propertyStr != null )
return PropertyItems.FirstOrDefault( ( prop ) => propertyStr == prop.PropertyDescriptor.Name );
return null;
}
public override object ItemFromContainer( PropertyItemBase container )
{
// Since this call is only used to update the PropertyGrid.SelectedProperty property,
// return the PropertyName.
var propertyItem = container as PropertyItem;
if( propertyItem == null )
return null;
return propertyItem.PropertyDescriptor.Name;
}
public override void UpdateValuesFromSource()
{
foreach( PropertyItem item in PropertyItems )
{
item.DescriptorDefinition.UpdateValueFromSource();
item.ContainerHelper.UpdateValuesFromSource();
}
}
public void GenerateProperties()
{
if( (PropertyItems.Count == 0)
)
{
this.RegenerateProperties();
}
}
protected override void OnFilterChanged()
{
this.UpdateFilter();
}
protected override void OnCategorizationChanged()
{
UpdateCategorization( true );
}
protected override void OnAutoGeneratePropertiesChanged()
{
this.RegenerateProperties();
}
protected override void OnHideInheritedPropertiesChanged()
{
this.RegenerateProperties();
}
protected override void OnEditorDefinitionsChanged()
{
this.RegenerateProperties();
}
protected override void OnPropertyDefinitionsChanged()
{
this.RegenerateProperties();
}
protected internal override void SetPropertiesExpansion( bool isExpanded )
{
if( this.Properties.Count == 0 )
{
this.GenerateProperties();
}
base.SetPropertiesExpansion( isExpanded );
}
protected internal override void SetPropertiesExpansion( string propertyName, bool isExpanded )
{
if( this.Properties.Count == 0 )
{
this.GenerateProperties();
}
base.SetPropertiesExpansion( propertyName, isExpanded );
}
private void UpdateFilter()
{
FilterInfo filterInfo = PropertyContainer.FilterInfo;
PropertyItems.FilterPredicate = filterInfo.Predicate
?? PropertyItemCollection.CreateFilter( filterInfo.InputString );
}
private void UpdateCategorization( bool updateSubPropertiesCategorization )
{
_propertyItemCollection.UpdateCategorization( this.ComputeCategoryGroupDescription(), this.PropertyContainer.IsCategorized, this.PropertyContainer.IsSortedAlphabetically );
if( updateSubPropertiesCategorization && (_propertyItemCollection.Count > 0) )
{
foreach( PropertyItem propertyItem in _propertyItemCollection )
{
PropertyItemCollection subPropertyItemsCollection = propertyItem.Properties as PropertyItemCollection;
if( subPropertyItemsCollection != null )
{
subPropertyItemsCollection.UpdateCategorization( this.ComputeCategoryGroupDescription(), this.PropertyContainer.IsCategorized, this.PropertyContainer.IsSortedAlphabetically );
}
}
}
}
private GroupDescription ComputeCategoryGroupDescription()
{
if( !PropertyContainer.IsCategorized )
return null;
return new PropertyGroupDescription( PropertyItemCollection.CategoryPropertyName );
}
private string GetCategoryGroupingPropertyName()
{
var propGroup = this.ComputeCategoryGroupDescription() as PropertyGroupDescription;
return ( propGroup != null ) ? propGroup.PropertyName : null;
}
private void OnChildrenPropertyChanged( object sender, PropertyChangedEventArgs e )
{
if( ObjectContainerHelperBase.IsItemOrderingProperty( e.PropertyName )
|| this.GetCategoryGroupingPropertyName() == e.PropertyName )
{
// Refreshing the view while Containers are generated will throw an exception
if( this.ChildrenItemsControl.ItemContainerGenerator.Status != GeneratorStatus.GeneratingContainers
&& !_isPreparingItemFlag )
{
PropertyItems.RefreshView();
}
}
}
protected abstract string GetDefaultPropertyName();
protected abstract IEnumerable<PropertyItem> GenerateSubPropertiesCore();
private void RegenerateProperties()
{
IEnumerable<PropertyItem> subProperties = this.GenerateSubPropertiesCore();
foreach( var propertyItem in subProperties )
{
this.InitializePropertyItem( propertyItem );
}
//Remove the event callback from the previous children (if any)
foreach( var propertyItem in PropertyItems )
{
propertyItem.PropertyChanged -= OnChildrenPropertyChanged;
}
PropertyItems.UpdateItems( subProperties );
//Add the event callback to the new childrens
foreach( var propertyItem in PropertyItems )
{
propertyItem.PropertyChanged += OnChildrenPropertyChanged;
}
// Update the selected property on the property grid only.
PropertyGrid propertyGrid = PropertyContainer as PropertyGrid;
if( propertyGrid != null )
{
propertyGrid.SelectedPropertyItem = this.DefaultProperty;
}
}
protected static List<PropertyDescriptor> GetPropertyDescriptors( object instance, bool hideInheritedProperties )
{
PropertyDescriptorCollection descriptors;
TypeConverter tc = TypeDescriptor.GetConverter( instance );
if( tc == null || !tc.GetPropertiesSupported() )
{
if( instance is ICustomTypeDescriptor )
{
descriptors = ((ICustomTypeDescriptor)instance).GetProperties();
}
//ICustomTypeProvider is only available in .net 4.5 and over. Use reflection so the .net 4.0 and .net 3.5 still works.
else if( instance.GetType().GetInterface( "ICustomTypeProvider", true ) != null )
{
var methodInfo = instance.GetType().GetMethod( "GetCustomType" );
var result = methodInfo.Invoke( instance, null ) as Type;
descriptors = TypeDescriptor.GetProperties( result );
}
else
{
descriptors = TypeDescriptor.GetProperties( instance.GetType() );
}
}
else
{
descriptors = tc.GetProperties( instance );
}
if( ( descriptors != null ) )
{
var descriptorsProperties = descriptors.Cast<PropertyDescriptor>();
if( hideInheritedProperties )
{
var properties = from p in descriptorsProperties
where p.ComponentType == instance.GetType()
select p;
return properties.ToList();
}
else
{
return descriptorsProperties.ToList();
}
}
return null;
}
protected bool GetWillRefreshPropertyGrid( PropertyDescriptor propertyDescriptor )
{
if( propertyDescriptor == null )
return false;
var attribute = PropertyGridUtilities.GetAttribute<RefreshPropertiesAttribute>( propertyDescriptor );
if( attribute != null )
return attribute.RefreshProperties != RefreshProperties.None;
return false;
}
internal void InitializeDescriptorDefinition(
DescriptorPropertyDefinitionBase descriptorDef,
PropertyDefinition propertyDefinition )
{
if( descriptorDef == null )
throw new ArgumentNullException( "descriptorDef" );
if( propertyDefinition == null )
return;
// Values defined on PropertyDefinition have priority on the attributes
if( propertyDefinition != null )
{
if( propertyDefinition.Category != null )
{
descriptorDef.Category = propertyDefinition.Category;
descriptorDef.CategoryValue = propertyDefinition.Category;
}
if( propertyDefinition.Description != null )
{
descriptorDef.Description = propertyDefinition.Description;
}
if( propertyDefinition.DisplayName != null )
{
descriptorDef.DisplayName = propertyDefinition.DisplayName;
}
if( propertyDefinition.DisplayOrder != null )
{
descriptorDef.DisplayOrder = propertyDefinition.DisplayOrder.Value;
}
if( propertyDefinition.IsExpandable != null )
{
descriptorDef.ExpandableAttribute = propertyDefinition.IsExpandable.Value;
}
}
}
private void InitializePropertyItem( PropertyItem propertyItem )
{
DescriptorPropertyDefinitionBase pd = propertyItem.DescriptorDefinition;
propertyItem.PropertyDescriptor = pd.PropertyDescriptor;
propertyItem.IsReadOnly = pd.IsReadOnly;
propertyItem.DisplayName = pd.DisplayName;
propertyItem.Description = pd.Description;
propertyItem.Category = pd.Category;
propertyItem.PropertyOrder = pd.DisplayOrder;
//These properties can vary with the value. They need to be bound.
if( pd.PropertyDescriptor.Converter is ExpandableObjectConverter )
{
propertyItem.IsExpandable = true;
}
else
{
SetupDefinitionBinding( propertyItem, PropertyItemBase.IsExpandableProperty, pd, () => pd.IsExpandable, BindingMode.OneWay );
}
SetupDefinitionBinding( propertyItem, PropertyItemBase.AdvancedOptionsIconProperty, pd, () => pd.AdvancedOptionsIcon, BindingMode.OneWay );
SetupDefinitionBinding( propertyItem, PropertyItemBase.AdvancedOptionsTooltipProperty, pd, () => pd.AdvancedOptionsTooltip, BindingMode.OneWay );
SetupDefinitionBinding( propertyItem, PropertyItem.ValueProperty, pd, () => pd.Value, BindingMode.TwoWay );
if( pd.CommandBindings != null )
{
foreach( CommandBinding commandBinding in pd.CommandBindings )
{
propertyItem.CommandBindings.Add( commandBinding );
}
}
}
private void SetupDefinitionBinding<T>(
PropertyItem propertyItem,
DependencyProperty itemProperty,
DescriptorPropertyDefinitionBase pd,
Expression<Func<T>> definitionProperty,
BindingMode bindingMode )
{
string sourceProperty = ReflectionHelper.GetPropertyOrFieldName( definitionProperty );
Binding binding = new Binding( sourceProperty )
{
Source = pd,
Mode = bindingMode
};
propertyItem.SetBinding( itemProperty, binding );
}
internal FrameworkElement GenerateChildrenEditorElement( PropertyItem propertyItem )
{
FrameworkElement editorElement = null;
DescriptorPropertyDefinitionBase pd = propertyItem.DescriptorDefinition;
object definitionKey = null;
Type definitionKeyAsType = definitionKey as Type;
ITypeEditor editor = null;
if( editor == null )
editor = pd.CreateAttributeEditor();
if( editor != null )
editorElement = editor.ResolveEditor( propertyItem );
if( editorElement == null && definitionKey == null )
editorElement = this.GenerateCustomEditingElement( propertyItem.PropertyDescriptor.Name, propertyItem );
if( editorElement == null && definitionKeyAsType == null )
editorElement = this.GenerateCustomEditingElement( propertyItem.PropertyType, propertyItem );
if( editorElement == null )
{
if( pd.IsReadOnly )
editor = new TextBlockEditor();
// Fallback: Use a default type editor.
if( editor == null )
{
editor = ( definitionKeyAsType != null )
? PropertyGridUtilities.CreateDefaultEditor( definitionKeyAsType, null, propertyItem )
: pd.CreateDefaultEditor( propertyItem );
}
Debug.Assert( editor != null );
editorElement = editor.ResolveEditor( propertyItem );
}
return editorElement;
}
internal PropertyDefinition GetPropertyDefinition( PropertyDescriptor descriptor )
{
PropertyDefinition def = null;
var propertyDefs = this.PropertyContainer.PropertyDefinitions;
if( propertyDefs != null )
{
def = propertyDefs[ descriptor.Name ];
if( def == null )
{
def = propertyDefs.GetRecursiveBaseTypes( descriptor.PropertyType );
}
}
return def;
}
public override void PrepareChildrenPropertyItem( PropertyItemBase propertyItem, object item )
{
_isPreparingItemFlag = true;
base.PrepareChildrenPropertyItem( propertyItem, item );
if( propertyItem.Editor == null )
{
FrameworkElement editor = this.GenerateChildrenEditorElement( ( PropertyItem )propertyItem );
if( editor != null )
{
// Tag the editor as generated to know if we should clear it.
ContainerHelperBase.SetIsGenerated( editor, true );
propertyItem.Editor = editor;
}
}
_isPreparingItemFlag = false;
}
public override void ClearChildrenPropertyItem( PropertyItemBase propertyItem, object item )
{
if( propertyItem.Editor != null
&& ContainerHelperBase.GetIsGenerated( propertyItem.Editor ) )
{
propertyItem.Editor = null;
}
base.ClearChildrenPropertyItem( propertyItem, item );
}
public override Binding CreateChildrenDefaultBinding( PropertyItemBase propertyItem )
{
Binding binding = new Binding( "Value" );
binding.Mode = ( ( ( PropertyItem )propertyItem ).IsReadOnly ) ? BindingMode.OneWay : BindingMode.TwoWay;
return binding;
}
protected static string GetDefaultPropertyName( object instance )
{
AttributeCollection attributes = TypeDescriptor.GetAttributes( instance );
DefaultPropertyAttribute defaultPropertyAttribute = ( DefaultPropertyAttribute )attributes[ typeof( DefaultPropertyAttribute ) ];
return defaultPropertyAttribute != null ? defaultPropertyAttribute.Name : null;
}
private static bool IsItemOrderingProperty( string propertyName )
{
return string.Equals( propertyName, PropertyItemCollection.DisplayNamePropertyName )
|| string.Equals( propertyName, PropertyItemCollection.CategoryOrderPropertyName )
|| string.Equals( propertyName, PropertyItemCollection.PropertyOrderPropertyName );
}
}
}

View File

@@ -0,0 +1,122 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public class PropertyDefinition : PropertyDefinitionBase
{
private string _name;
private bool? _isBrowsable = true;
private bool? _isExpandable = null;
private string _displayName = null;
private string _description = null;
private string _category = null;
private int? _displayOrder = null;
[Obsolete(@"Use 'TargetProperties' instead of 'Name'")]
public string Name
{
get { return _name; }
set
{
const string usageError = "{0}: \'Name\' property is obsolete. Instead use \'TargetProperties\'. (XAML example: <t:PropertyDefinition TargetProperties=\"FirstName,LastName\" />)";
System.Diagnostics.Trace.TraceWarning( usageError, typeof( PropertyDefinition ) );
_name = value;
}
}
public string Category
{
get { return _category; }
set
{
this.ThrowIfLocked( () => this.Category );
_category = value;
}
}
public string DisplayName
{
get { return _displayName; }
set
{
this.ThrowIfLocked( () => this.DisplayName );
_displayName = value;
}
}
public string Description
{
get { return _description; }
set
{
this.ThrowIfLocked( () => this.Description );
_description = value;
}
}
public int? DisplayOrder
{
get { return _displayOrder; }
set
{
this.ThrowIfLocked( () => this.DisplayOrder );
_displayOrder = value;
}
}
public bool? IsBrowsable
{
get { return _isBrowsable; }
set
{
this.ThrowIfLocked( () => this.IsBrowsable );
_isBrowsable = value;
}
}
public bool? IsExpandable
{
get { return _isExpandable; }
set
{
this.ThrowIfLocked( () => this.IsExpandable );
_isExpandable = value;
}
}
internal override void Lock()
{
if( _name != null
&& this.TargetProperties != null
&& this.TargetProperties.Count > 0 )
{
throw new InvalidOperationException(
string.Format(
@"{0}: When using 'TargetProperties' property, do not use 'Name' property.",
typeof( PropertyDefinition ) ) );
}
if( _name != null )
{
this.TargetProperties = new List<object>() { _name };
}
base.Lock();
}
}
}

View File

@@ -0,0 +1,124 @@
/*************************************************************************************
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.Collections.ObjectModel;
using System.Linq;
using System.Windows.Documents;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public class PropertyDefinitionCollection : PropertyDefinitionBaseCollection<PropertyDefinition>
{
}
public class EditorDefinitionCollection : PropertyDefinitionBaseCollection<EditorDefinitionBase>
{
}
public abstract class PropertyDefinitionBaseCollection<T> : DefinitionCollectionBase<T> where T : PropertyDefinitionBase
{
protected PropertyDefinitionBaseCollection()
{
}
public virtual T this[ object propertyId ]
{
get
{
foreach( var item in Items )
{
if( item.TargetProperties.Contains( propertyId ) )
return item;
// Using the special character "*" in a string of TargetProperties will
// return all the items containing the string (before or after) the "*".
// ex : Prop* will return properties named Prop1, Prop2, Prop3...
List<string> stringTargetProperties = item.TargetProperties.OfType<string>().ToList();
if( ( stringTargetProperties != null ) && ( stringTargetProperties.Count > 0 ) )
{
if( propertyId is string )
{
string stringPropertyID = ( string )propertyId;
foreach( var targetPropertyString in stringTargetProperties )
{
if( targetPropertyString.Contains( "*" ) )
{
string searchString = targetPropertyString.Replace( "*", "" );
if( stringPropertyID.StartsWith( searchString ) || stringPropertyID.EndsWith( searchString ) )
return item;
}
}
}
}
else
{
//Manage Interfaces
var type = propertyId as Type;
if( type != null )
{
foreach( Type targetProperty in item.TargetProperties )
{
if( targetProperty.IsAssignableFrom( type ) )
return item;
}
}
}
}
return null;
}
}
internal T GetRecursiveBaseTypes( Type type )
{
// If no definition for the current type, fall back on base type editor recursively.
T ret = null;
while( ret == null && type != null )
{
ret = this[ type ];
type = type.BaseType;
}
return ret;
}
}
public abstract class DefinitionCollectionBase<T> : ObservableCollection<T> where T : DefinitionBase
{
internal DefinitionCollectionBase()
{
}
protected override void InsertItem( int index, T item )
{
if( item == null )
throw new InvalidOperationException( @"Cannot insert null items in the collection." );
item.Lock();
base.InsertItem( index, item );
}
protected override void SetItem( int index, T item )
{
if( item == null )
throw new InvalidOperationException( @"Cannot insert null items in the collection." );
item.Lock();
base.SetItem( index, item );
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,210 @@
/*************************************************************************************
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.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
using System.Linq.Expressions;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.Core.Utilities;
using System.Windows.Controls;
using System.Reflection;
using System.Windows.Controls.Primitives;
using Xceed.Wpf.Toolkit.PropertyGrid.Converters;
using Xceed.Wpf.Toolkit.Primitives;
using System.IO;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal class PropertyGridUtilities
{
internal static T GetAttribute<T>( PropertyDescriptor property ) where T : Attribute
{
return property.Attributes.OfType<T>().FirstOrDefault();
}
internal static ITypeEditor CreateDefaultEditor( Type propertyType, TypeConverter typeConverter, PropertyItem propertyItem )
{
ITypeEditor editor = null;
var context = new EditorTypeDescriptorContext( null, propertyItem.Instance, propertyItem.PropertyDescriptor );
if( (typeConverter != null)
&& typeConverter.GetStandardValuesSupported( context )
&& typeConverter.GetStandardValuesExclusive( context )
&& (propertyType != typeof( bool )) && (propertyType != typeof( bool? )) ) //Bool type always have a BooleanConverter with standardValues : True/False.
{
var items = typeConverter.GetStandardValues( context );
editor = new SourceComboBoxEditor( items, typeConverter );
}
else if( propertyType == typeof( string ) )
editor = new TextBoxEditor();
else if( propertyType == typeof( bool ) || propertyType == typeof( bool? ) )
editor = new CheckBoxEditor();
else if( propertyType == typeof( decimal ) || propertyType == typeof( decimal? ) )
editor = new DecimalUpDownEditor();
else if( propertyType == typeof( double ) || propertyType == typeof( double? ) )
editor = new DoubleUpDownEditor();
else if( propertyType == typeof( int ) || propertyType == typeof( int? ) )
editor = new IntegerUpDownEditor();
else if( propertyType == typeof( short ) || propertyType == typeof( short? ) )
editor = new ShortUpDownEditor();
else if( propertyType == typeof( long ) || propertyType == typeof( long? ) )
editor = new LongUpDownEditor();
else if( propertyType == typeof( float ) || propertyType == typeof( float? ) )
editor = new SingleUpDownEditor();
else if( propertyType == typeof( byte ) || propertyType == typeof( byte? ) )
editor = new ByteUpDownEditor();
else if( propertyType == typeof( sbyte ) || propertyType == typeof( sbyte? ) )
editor = new SByteUpDownEditor();
else if( propertyType == typeof( uint ) || propertyType == typeof( uint? ) )
editor = new UIntegerUpDownEditor();
else if( propertyType == typeof( ulong ) || propertyType == typeof( ulong? ) )
editor = new ULongUpDownEditor();
else if( propertyType == typeof( ushort ) || propertyType == typeof( ushort? ) )
editor = new UShortUpDownEditor();
else if( propertyType == typeof( DateTime ) || propertyType == typeof( DateTime? ) )
editor = new DateTimeUpDownEditor();
else if( ( propertyType == typeof( Color ) ) || ( propertyType == typeof( Color? ) ) )
editor = new ColorEditor();
else if( propertyType.IsEnum )
editor = new EnumComboBoxEditor();
else if( propertyType == typeof( TimeSpan ) || propertyType == typeof( TimeSpan? ) )
editor = new TimeSpanUpDownEditor();
else if( propertyType == typeof( FontFamily ) || propertyType == typeof( FontWeight ) || propertyType == typeof( FontStyle ) || propertyType == typeof( FontStretch ) )
editor = new FontComboBoxEditor();
else if (propertyType == typeof(Guid) || propertyType == typeof(Guid?))
editor = new MaskedTextBoxEditor() { ValueDataType = propertyType, Mask = "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA" };
else if (propertyType == typeof(char) || propertyType == typeof(char?))
editor = new MaskedTextBoxEditor() { ValueDataType = propertyType, Mask = "&" };
else if( propertyType == typeof( object ) )
// If any type of object is possible in the property, default to the TextBoxEditor.
// Useful in some case (e.g., Button.Content).
// Can be reconsidered but was the legacy behavior on the PropertyGrid.
editor = new TextBoxEditor();
else
{
var listType = ListUtilities.GetListItemType( propertyType );
// A List of T
if( listType != null )
{
if( !listType.IsPrimitive && !listType.Equals( typeof( String ) ) && !listType.IsEnum )
editor = new Xceed.Wpf.Toolkit.PropertyGrid.Editors.CollectionEditor();
else
editor = new Xceed.Wpf.Toolkit.PropertyGrid.Editors.PrimitiveTypeCollectionEditor();
}
else
{
var dictionaryType = ListUtilities.GetDictionaryItemsType( propertyType );
var collectionType = ListUtilities.GetCollectionItemType( propertyType );
// A dictionary of T or a Collection of T or an ICollection
if( (dictionaryType != null) || (collectionType != null) || typeof( ICollection ).IsAssignableFrom( propertyType ) )
{
editor = new Xceed.Wpf.Toolkit.PropertyGrid.Editors.CollectionEditor();
}
else
{
// If the type is not supported, check if there is a converter that supports
// string conversion to the object type. Use TextBox in theses cases.
// Otherwise, return a TextBlock editor since no valid editor exists.
editor = (typeConverter != null && typeConverter.CanConvertFrom( typeof( string ) ))
? (ITypeEditor)new TextBoxEditor()
: (ITypeEditor)new TextBlockEditor();
}
}
}
return editor;
}
#region Private class
private class EditorTypeDescriptorContext : ITypeDescriptorContext
{
IContainer _container;
object _instance;
PropertyDescriptor _propertyDescriptor;
internal EditorTypeDescriptorContext( IContainer container, object instance, PropertyDescriptor pd )
{
_container = container;
_instance = instance;
_propertyDescriptor = pd;
}
IContainer ITypeDescriptorContext.Container
{
get
{
return _container;
}
}
object ITypeDescriptorContext.Instance
{
get
{
return _instance;
}
}
PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
{
get
{
return _propertyDescriptor;
}
}
void ITypeDescriptorContext.OnComponentChanged()
{
}
bool ITypeDescriptorContext.OnComponentChanging()
{
return false;
}
object IServiceProvider.GetService( Type serviceType )
{
return null;
}
}
#endregion
}
}

View File

@@ -0,0 +1,210 @@
/*************************************************************************************
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.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Data;
using System.Collections;
using Xceed.Wpf.Toolkit.Core.Utilities;
using System.Linq.Expressions;
using System.Diagnostics;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
[TemplatePart( Name = "content", Type = typeof( ContentControl ) )]
public class PropertyItem : CustomPropertyItem
{
#region Properties
#region IsReadOnly
/// <summary>
/// Identifies the IsReadOnly dependency property
/// </summary>
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( PropertyItem ), new UIPropertyMetadata( false ) );
public bool IsReadOnly
{
get { return ( bool )GetValue( IsReadOnlyProperty ); }
set { SetValue( IsReadOnlyProperty, value ); }
}
#endregion //IsReadOnly
#region PropertyDescriptor
public PropertyDescriptor PropertyDescriptor
{
get;
internal set;
}
#endregion //PropertyDescriptor
#region PropertyName
public string PropertyName
{
get
{
return (this.DescriptorDefinition != null) ? this.DescriptorDefinition.PropertyName : null;
}
}
#endregion
#region PropertyType
public Type PropertyType
{
get
{
return ( PropertyDescriptor != null )
? PropertyDescriptor.PropertyType
: null;
}
}
#endregion //PropertyType
#region DescriptorDefinition
internal DescriptorPropertyDefinitionBase DescriptorDefinition
{
get;
private set;
}
#endregion DescriptorDefinition
#region Instance
public object Instance
{
get;
internal set;
}
#endregion //Instance
#endregion //Properties
#region Overrides
protected override string GetPropertyItemName()
{
return this.PropertyName;
}
protected override Type GetPropertyItemType()
{
return this.PropertyType;
}
#endregion
#region Methods
protected override void OnIsExpandedChanged( bool oldValue, bool newValue )
{
if( newValue )
{
// This withholds the generation of all PropertyItem instances (recursively)
// until the PropertyItem is expanded.
var objectContainerHelper = ContainerHelper as ObjectContainerHelperBase;
if( objectContainerHelper != null )
{
objectContainerHelper.GenerateProperties();
}
}
}
protected override object OnCoerceValueChanged( object baseValue )
{
// Propagate error from DescriptorPropertyDefinitionBase to PropertyItem.Value
// to see the red error rectangle in the propertyGrid.
BindingExpression be = this.GetBindingExpression( PropertyItem.ValueProperty );
this.SetRedInvalidBorder( be );
return baseValue;
}
protected override void OnValueChanged( object oldValue, object newValue )
{
base.OnValueChanged( oldValue, newValue );
}
internal void SetRedInvalidBorder( BindingExpression be )
{
if( (be != null) && be.DataItem is DescriptorPropertyDefinitionBase )
{
DescriptorPropertyDefinitionBase descriptor = be.DataItem as DescriptorPropertyDefinitionBase;
if( Validation.GetHasError( descriptor ) )
{
ReadOnlyObservableCollection<ValidationError> errors = Validation.GetErrors( descriptor );
Validation.MarkInvalid( be, errors[ 0 ] );
}
}
}
private void OnDefinitionContainerHelperInvalidated( object sender, EventArgs e )
{
if( this.ContainerHelper != null )
{
this.ContainerHelper.ClearHelper();
}
var helper = this.DescriptorDefinition.CreateContainerHelper( this );
this.ContainerHelper = helper;
if( this.IsExpanded )
{
helper.GenerateProperties();
}
}
private void Init( DescriptorPropertyDefinitionBase definition )
{
if( definition == null )
throw new ArgumentNullException( "definition" );
if( this.ContainerHelper != null )
{
this.ContainerHelper.ClearHelper();
}
this.DescriptorDefinition = definition;
this.ContainerHelper = definition.CreateContainerHelper( this );
definition.ContainerHelperInvalidated += new EventHandler( OnDefinitionContainerHelperInvalidated );
}
#endregion
#region Constructors
internal PropertyItem( DescriptorPropertyDefinitionBase definition )
: base( definition.IsPropertyGridCategorized, !definition.PropertyType.IsArray )
{
this.Init( definition );
}
#endregion //Constructors
}
}

View File

@@ -0,0 +1,572 @@
/*************************************************************************************
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.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Data;
using System.Collections;
using Xceed.Wpf.Toolkit.Core.Utilities;
using System.Reflection;
using System.Linq.Expressions;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
[TemplatePart( Name = PropertyGrid.PART_PropertyItemsControl, Type = typeof( PropertyItemsControl ) )]
[TemplatePart( Name = PropertyItemBase.PART_ValueContainer, Type = typeof( ContentControl ) )]
public abstract class PropertyItemBase : Control, IPropertyContainer, INotifyPropertyChanged
{
internal const string PART_ValueContainer = "PART_ValueContainer";
private ContentControl _valueContainer;
private ContainerHelperBase _containerHelper;
private IPropertyContainer _parentNode;
internal bool _isPropertyGridCategorized;
internal bool _isSortedAlphabetically = true;
#region Properties
#region AdvancedOptionsIcon
public static readonly DependencyProperty AdvancedOptionsIconProperty =
DependencyProperty.Register( "AdvancedOptionsIcon", typeof( ImageSource ), typeof( PropertyItemBase ), new UIPropertyMetadata( null ) );
public ImageSource AdvancedOptionsIcon
{
get { return ( ImageSource )GetValue( AdvancedOptionsIconProperty ); }
set { SetValue( AdvancedOptionsIconProperty, value ); }
}
#endregion //AdvancedOptionsIcon
#region AdvancedOptionsTooltip
public static readonly DependencyProperty AdvancedOptionsTooltipProperty =
DependencyProperty.Register( "AdvancedOptionsTooltip", typeof( object ), typeof( PropertyItemBase ), new UIPropertyMetadata( null ) );
public object AdvancedOptionsTooltip
{
get { return ( object )GetValue( AdvancedOptionsTooltipProperty ); }
set { SetValue( AdvancedOptionsTooltipProperty, value ); }
}
#endregion //AdvancedOptionsTooltip
#region Description
public static readonly DependencyProperty DescriptionProperty =
DependencyProperty.Register( "Description", typeof( string ), typeof( PropertyItemBase ), new UIPropertyMetadata( null ) );
public string Description
{
get { return ( string )GetValue( DescriptionProperty ); }
set { SetValue( DescriptionProperty, value ); }
}
#endregion //Description
#region DisplayName
public static readonly DependencyProperty DisplayNameProperty =
DependencyProperty.Register( "DisplayName", typeof( string ), typeof( PropertyItemBase ), new UIPropertyMetadata( null ) );
public string DisplayName
{
get { return ( string )GetValue( DisplayNameProperty ); }
set { SetValue( DisplayNameProperty, value ); }
}
#endregion //DisplayName
#region Editor
public static readonly DependencyProperty EditorProperty = DependencyProperty.Register( "Editor", typeof( FrameworkElement ), typeof( PropertyItemBase ), new UIPropertyMetadata( null, OnEditorChanged ) );
public FrameworkElement Editor
{
get
{
return ( FrameworkElement )GetValue( EditorProperty );
}
set
{
SetValue( EditorProperty, value );
}
}
private static void OnEditorChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PropertyItemBase propertyItem = o as PropertyItemBase;
if( propertyItem != null )
propertyItem.OnEditorChanged( ( FrameworkElement )e.OldValue, ( FrameworkElement )e.NewValue );
}
protected virtual void OnEditorChanged( FrameworkElement oldValue, FrameworkElement newValue )
{
}
#endregion //Editor
#region IsExpanded
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register( "IsExpanded", typeof( bool ), typeof( PropertyItemBase ), new UIPropertyMetadata( false, OnIsExpandedChanged ) );
public bool IsExpanded
{
get
{
return ( bool )GetValue( IsExpandedProperty );
}
set
{
SetValue( IsExpandedProperty, value );
}
}
private static void OnIsExpandedChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PropertyItemBase propertyItem = o as PropertyItemBase;
if( propertyItem != null )
propertyItem.OnIsExpandedChanged( ( bool )e.OldValue, ( bool )e.NewValue );
}
protected virtual void OnIsExpandedChanged( bool oldValue, bool newValue )
{
}
#endregion IsExpanded
#region IsExpandable
public static readonly DependencyProperty IsExpandableProperty =
DependencyProperty.Register( "IsExpandable", typeof( bool ), typeof( PropertyItemBase ), new UIPropertyMetadata( false ) );
public bool IsExpandable
{
get { return ( bool )GetValue( IsExpandableProperty ); }
set { SetValue( IsExpandableProperty, value ); }
}
#endregion //IsExpandable
#region IsSelected
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( "IsSelected", typeof( bool ), typeof( PropertyItemBase ), new UIPropertyMetadata( false, OnIsSelectedChanged ) );
public bool IsSelected
{
get
{
return ( bool )GetValue( IsSelectedProperty );
}
set
{
SetValue( IsSelectedProperty, value );
}
}
private static void OnIsSelectedChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PropertyItemBase propertyItem = o as PropertyItemBase;
if( propertyItem != null )
propertyItem.OnIsSelectedChanged( ( bool )e.OldValue, ( bool )e.NewValue );
}
protected virtual void OnIsSelectedChanged( bool oldValue, bool newValue )
{
this.RaiseItemSelectionChangedEvent();
}
#endregion //IsSelected
#region ParentElement
/// <summary>
/// Gets the parent property grid element of this property.
/// A PropertyItemBase instance if this is a sub-element,
/// or the PropertyGrid itself if this is a first-level property.
/// </summary>
public FrameworkElement ParentElement
{
get { return this.ParentNode as FrameworkElement; }
}
#endregion
#region ParentNode
internal IPropertyContainer ParentNode
{
get
{
return _parentNode;
}
set
{
_parentNode = value;
}
}
#endregion
#region ValueContainer
internal ContentControl ValueContainer
{
get
{
return _valueContainer;
}
}
#endregion
#region Level
public int Level
{
get;
internal set;
}
#endregion //Level
#region Properties
public IList Properties
{
get
{
return _containerHelper.Properties;
}
}
#endregion //Properties
#region PropertyContainerStyle
/// <summary>
/// Get the PropertyContainerStyle for sub items of this property.
/// It return the value defined on PropertyGrid.PropertyContainerStyle.
/// </summary>
public Style PropertyContainerStyle
{
get
{
return ( ParentNode != null )
? ParentNode.PropertyContainerStyle
: null;
}
}
#endregion
#region ContainerHelper
internal ContainerHelperBase ContainerHelper
{
get
{
return _containerHelper;
}
set
{
if( value == null )
throw new ArgumentNullException( "value" );
_containerHelper = value;
// Properties property relies on the "Properties" property of the helper
// class. Raise a property-changed event.
this.RaisePropertyChanged( () => this.Properties );
}
}
#endregion
#region WillRefreshPropertyGrid
public static readonly DependencyProperty WillRefreshPropertyGridProperty =
DependencyProperty.Register( "WillRefreshPropertyGrid", typeof( bool ), typeof( PropertyItemBase ), new UIPropertyMetadata( false ) );
public bool WillRefreshPropertyGrid
{
get
{
return ( bool )GetValue( WillRefreshPropertyGridProperty );
}
set
{
SetValue( WillRefreshPropertyGridProperty, value );
}
}
#endregion //WillRefreshPropertyGrid
#endregion //Properties
#region Events
#region ItemSelectionChanged
internal static readonly RoutedEvent ItemSelectionChangedEvent = EventManager.RegisterRoutedEvent(
"ItemSelectionChangedEvent", RoutingStrategy.Bubble, typeof( RoutedEventHandler ), typeof( PropertyItemBase ) );
private void RaiseItemSelectionChangedEvent()
{
RaiseEvent( new RoutedEventArgs( PropertyItemBase.ItemSelectionChangedEvent ) );
}
#endregion
#region PropertyChanged event
public event PropertyChangedEventHandler PropertyChanged;
internal void RaisePropertyChanged<TMember>( Expression<Func<TMember>> propertyExpression )
{
this.Notify( this.PropertyChanged, propertyExpression );
}
internal void RaisePropertyChanged( string name )
{
this.Notify( this.PropertyChanged, name );
}
#endregion
#endregion //Events
#region Constructors
static PropertyItemBase()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyItemBase ), new FrameworkPropertyMetadata( typeof( PropertyItemBase ) ) );
}
internal PropertyItemBase()
{
_containerHelper = new ObjectContainerHelper( this, null );
this.GotFocus += new RoutedEventHandler( PropertyItemBase_GotFocus );
AddHandler( PropertyItemsControl.PreparePropertyItemEvent, new PropertyItemEventHandler( OnPreparePropertyItemInternal ) );
AddHandler( PropertyItemsControl.ClearPropertyItemEvent, new PropertyItemEventHandler( OnClearPropertyItemInternal ) );
}
#endregion //Constructors
#region Event Handlers
private void OnPreparePropertyItemInternal( object sender, PropertyItemEventArgs args )
{
// This is the callback of the PreparePropertyItem comming from the template PropertyItemControl.
args.PropertyItem.Level = this.Level + 1;
_containerHelper.PrepareChildrenPropertyItem( args.PropertyItem, args.Item );
args.Handled = true;
}
private void OnClearPropertyItemInternal( object sender, PropertyItemEventArgs args )
{
_containerHelper.ClearChildrenPropertyItem( args.PropertyItem, args.Item );
// This is the callback of the PreparePropertyItem comming from the template PropertyItemControl.
args.PropertyItem.Level = 0;
args.Handled = true;
}
#endregion //Event Handlers
#region Methods
protected virtual Type GetPropertyItemType()
{
return null;
}
protected virtual string GetPropertyItemName()
{
return this.DisplayName;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_containerHelper.ChildrenItemsControl = GetTemplateChild( PropertyGrid.PART_PropertyItemsControl ) as PropertyItemsControl;
_valueContainer = GetTemplateChild( PropertyItemBase.PART_ValueContainer ) as ContentControl;
}
protected override void OnMouseDown( MouseButtonEventArgs e )
{
IsSelected = true;
if( !this.IsKeyboardFocusWithin )
{
this.Focus();
}
// Handle the event; otherwise, the possible
// parent property item will select itself too.
e.Handled = true;
}
private void PropertyItemBase_GotFocus( object sender, RoutedEventArgs e )
{
IsSelected = true;
// Handle the event; otherwise, the possible
// parent property item will select itself too.
e.Handled = true;
}
protected override void OnPropertyChanged( DependencyPropertyChangedEventArgs e )
{
base.OnPropertyChanged( e );
// First check that the raised property is actually a real CLR property.
// This could be something else like an Attached DP.
if( ReflectionHelper.IsPublicInstanceProperty( GetType(), e.Property.Name ) )
{
this.RaisePropertyChanged( e.Property.Name );
}
}
private PropertyDefinitionCollection GetPropertItemPropertyDefinitions()
{
if( (this.ParentNode != null) && (this.ParentNode.PropertyDefinitions != null) )
{
var name = this.GetPropertyItemName();
foreach( var pd in this.ParentNode.PropertyDefinitions )
{
if( pd.TargetProperties.Contains( name ) )
{
// PropertyDefinitions contains a PropertyDefinition for this PropertyItem Name => return its PropertyDefinitions.
return pd.PropertyDefinitions;
}
else
{
var type = this.GetPropertyItemType();
if( type != null )
{
foreach( var targetProperty in pd.TargetProperties )
{
var targetPropertyType = targetProperty as Type;
// PropertyDefinitions contains a PropertyDefinition for this PropertyItem Type => return its PropertyDefinitions.
if( (targetPropertyType != null) && targetPropertyType.IsAssignableFrom( type ) )
return pd.PropertyDefinitions;
}
}
}
}
}
return null;
}
#endregion //Methods
#region IPropertyContainer Members
Style IPropertyContainer.PropertyContainerStyle
{
get { return this.PropertyContainerStyle; }
}
EditorDefinitionCollection IPropertyContainer.EditorDefinitions
{
get
{
return (this.ParentNode != null) ? this.ParentNode.EditorDefinitions : null;
}
}
PropertyDefinitionCollection IPropertyContainer.PropertyDefinitions
{
get
{
return this.GetPropertItemPropertyDefinitions();
}
}
ContainerHelperBase IPropertyContainer.ContainerHelper
{
get
{
return this.ContainerHelper;
}
}
bool IPropertyContainer.IsCategorized
{
get
{
return _isPropertyGridCategorized;
}
}
bool IPropertyContainer.IsSortedAlphabetically
{
get
{
return _isSortedAlphabetically;
}
}
bool IPropertyContainer.AutoGenerateProperties
{
get
{
if( this.ParentNode != null )
{
var propertyItemPropertyDefinitions = this.GetPropertItemPropertyDefinitions();
// No PropertyDefinitions specified : show all properties of this PropertyItem.
if( (propertyItemPropertyDefinitions == null) || (propertyItemPropertyDefinitions.Count == 0) )
return true;
// A PropertyDefinitions is specified : show only the properties of the PropertyDefinitions from this PropertyItem.
return this.ParentNode.AutoGenerateProperties;
}
return true;
}
}
bool IPropertyContainer.HideInheritedProperties
{
get
{
return false;
}
}
FilterInfo IPropertyContainer.FilterInfo
{
get { return new FilterInfo(); }
}
bool? IPropertyContainer.IsPropertyVisible( PropertyDescriptor pd )
{
if( _parentNode != null )
{
return _parentNode.IsPropertyVisible( pd );
}
return null;
}
#endregion
}
}

View File

@@ -0,0 +1,185 @@
/*************************************************************************************
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.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;
using System;
using System.Collections.Specialized;
using System.Diagnostics;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.Linq;
using System.Collections;
using Xceed.Wpf.Toolkit.Core.Utilities;
#if !VS2008
using System.ComponentModel.DataAnnotations;
#endif
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public class PropertyItemCollection : ReadOnlyObservableCollection<PropertyItem>
{
internal static readonly string CategoryPropertyName;
internal static readonly string CategoryOrderPropertyName;
internal static readonly string PropertyOrderPropertyName;
internal static readonly string DisplayNamePropertyName;
private bool _preventNotification;
static PropertyItemCollection()
{
PropertyItem p = null;
CategoryPropertyName = ReflectionHelper.GetPropertyOrFieldName( () => p.Category );
CategoryOrderPropertyName = ReflectionHelper.GetPropertyOrFieldName( () => p.CategoryOrder );
PropertyOrderPropertyName = ReflectionHelper.GetPropertyOrFieldName( () => p.PropertyOrder );
DisplayNamePropertyName = ReflectionHelper.GetPropertyOrFieldName( () => p.DisplayName );
}
public PropertyItemCollection(ObservableCollection<PropertyItem> editableCollection)
:base(editableCollection)
{
EditableCollection = editableCollection;
}
internal Predicate<object> FilterPredicate
{
get { return GetDefaultView().Filter; }
set { GetDefaultView().Filter = value; }
}
public ObservableCollection<PropertyItem> EditableCollection { get; private set; }
private ICollectionView GetDefaultView()
{
return CollectionViewSource.GetDefaultView( this );
}
public void GroupBy( string name )
{
GetDefaultView().GroupDescriptions.Add( new PropertyGroupDescription( name ) );
}
public void SortBy( string name, ListSortDirection sortDirection )
{
GetDefaultView().SortDescriptions.Add( new SortDescription( name, sortDirection ) );
}
public void Filter( string text )
{
Predicate<object> filter = PropertyItemCollection.CreateFilter( text );
GetDefaultView().Filter = filter;
}
protected override void OnCollectionChanged( NotifyCollectionChangedEventArgs args )
{
if( _preventNotification )
return;
base.OnCollectionChanged( args );
}
internal void UpdateItems( IEnumerable<PropertyItem> newItems )
{
if( newItems == null )
throw new ArgumentNullException( "newItems" );
_preventNotification = true;
using( GetDefaultView().DeferRefresh() )
{
EditableCollection.Clear();
foreach( var item in newItems )
{
this.EditableCollection.Add( item );
}
}
_preventNotification = false;
OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) );
}
internal void UpdateCategorization( GroupDescription groupDescription, bool isPropertyGridCategorized, bool sortAlphabetically )
{
// Compute Display Order relative to PropertyOrderAttributes on PropertyItem
// which could be different in Alphabetical or Categorized mode.
foreach( PropertyItem item in this.Items )
{
item.DescriptorDefinition.DisplayOrder = item.DescriptorDefinition.ComputeDisplayOrderInternal( isPropertyGridCategorized );
item.PropertyOrder = item.DescriptorDefinition.DisplayOrder;
}
// Clear view values
ICollectionView view = this.GetDefaultView();
using( view.DeferRefresh() )
{
view.GroupDescriptions.Clear();
view.SortDescriptions.Clear();
// Update view values
if( groupDescription != null )
{
view.GroupDescriptions.Add( groupDescription );
if( sortAlphabetically )
{
SortBy( CategoryOrderPropertyName, ListSortDirection.Ascending );
SortBy( CategoryPropertyName, ListSortDirection.Ascending );
}
}
if( sortAlphabetically )
{
SortBy( PropertyOrderPropertyName, ListSortDirection.Ascending );
SortBy( DisplayNamePropertyName, ListSortDirection.Ascending );
}
}
}
internal void RefreshView()
{
GetDefaultView().Refresh();
}
internal static Predicate<object> CreateFilter( string text )
{
Predicate<object> filter = null;
if( !string.IsNullOrEmpty( text ) )
{
filter = ( item ) =>
{
var property = item as PropertyItem;
if( property.DisplayName != null )
{
#if !VS2008
var displayAttribute = PropertyGridUtilities.GetAttribute<DisplayAttribute>( property.PropertyDescriptor );
if( displayAttribute != null )
{
var canBeFiltered = displayAttribute.GetAutoGenerateFilter();
if( canBeFiltered.HasValue && !canBeFiltered.Value )
return false;
}
#endif
return property.DisplayName.ToLower().Contains( text.ToLower() );
}
return false;
};
}
return filter;
}
}
}

View File

@@ -0,0 +1,96 @@
/*************************************************************************************
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.Controls;
using System.Windows;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
/// <summary>
/// This Control is intended to be used in the template of the
/// PropertyItemBase and PropertyGrid classes to contain the
/// sub-children properties.
/// </summary>
public class PropertyItemsControl : ItemsControl
{
#region PreparePropertyItemEvent Attached Routed Event
internal static readonly RoutedEvent PreparePropertyItemEvent = EventManager.RegisterRoutedEvent( "PreparePropertyItem", RoutingStrategy.Bubble, typeof( PropertyItemEventHandler ), typeof( PropertyItemsControl ) );
internal event PropertyItemEventHandler PreparePropertyItem
{
add
{
AddHandler( PropertyItemsControl.PreparePropertyItemEvent, value );
}
remove
{
RemoveHandler( PropertyItemsControl.PreparePropertyItemEvent, value );
}
}
private void RaisePreparePropertyItemEvent( PropertyItemBase propertyItem, object item )
{
this.RaiseEvent( new PropertyItemEventArgs( PropertyItemsControl.PreparePropertyItemEvent, this, propertyItem, item ) );
}
#endregion
#region ClearPropertyItemEvent Attached Routed Event
internal static readonly RoutedEvent ClearPropertyItemEvent = EventManager.RegisterRoutedEvent( "ClearPropertyItem", RoutingStrategy.Bubble, typeof( PropertyItemEventHandler ), typeof( PropertyItemsControl ) );
internal event PropertyItemEventHandler ClearPropertyItem
{
add
{
AddHandler( PropertyItemsControl.ClearPropertyItemEvent, value );
}
remove
{
RemoveHandler( PropertyItemsControl.ClearPropertyItemEvent, value );
}
}
private void RaiseClearPropertyItemEvent( PropertyItemBase propertyItem, object item )
{
this.RaiseEvent( new PropertyItemEventArgs( PropertyItemsControl.ClearPropertyItemEvent, this, propertyItem, item ) );
}
#endregion
protected override bool IsItemItsOwnContainerOverride( object item )
{
return ( item is PropertyItemBase );
}
protected override void PrepareContainerForItemOverride( DependencyObject element, object item )
{
base.PrepareContainerForItemOverride( element, item );
this.RaisePreparePropertyItemEvent( ( PropertyItemBase )element, item );
}
protected override void ClearContainerForItemOverride( DependencyObject element, object item )
{
this.RaiseClearPropertyItemEvent( ( PropertyItemBase )element, item );
base.ClearContainerForItemOverride( element, item );
}
}
}

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;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public static class StringConstants
{
public static string Local
{
get { return "Local"; }
}
public static string Resource
{
get { return "Resource"; }
}
public static string Databinding
{
get { return "Databinding"; }
}
public static string Inheritance
{
get { return "Inheritance"; }
}
public static string StyleSetter
{
get { return "Style Setter"; }
}
public static string AdvancedProperties
{
get { return "Advanced Properties"; }
}
}
}

View File

@@ -0,0 +1,59 @@
/*************************************************************************************
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.Utilities;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
/// <summary>
/// This class is intended to provide the "Type" target
/// for property definitions or editor definitions when
/// using Property Element Syntax.
/// </summary>
public sealed class TargetPropertyType
{
private Type _type;
private bool _sealed;
public Type Type
{
get { return _type; }
set
{
if( _sealed )
throw new InvalidOperationException(
string.Format(
"{0}.Type property cannot be modified once the instance is used",
typeof( TargetPropertyType ) ) );
_type = value;
}
}
internal void Seal()
{
if( _type == null )
throw new InvalidOperationException(
string.Format( "{0}.Type property must be initialized", typeof( TargetPropertyType ) ) );
_sealed = true;
}
}
}

View File

@@ -0,0 +1,101 @@
/*************************************************************************************
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;
using System.Windows.Controls;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public class TrimmedTextBlock : TextBlock
{
#region Constructor
public TrimmedTextBlock()
{
this.SizeChanged += this.TrimmedTextBlock_SizeChanged;
}
#endregion
#region IsTextTrimmed Property
public static readonly DependencyProperty IsTextTrimmedProperty = DependencyProperty.Register( "IsTextTrimmed", typeof( bool ), typeof( TrimmedTextBlock ), new PropertyMetadata( false, OnIsTextTrimmedChanged ) );
public bool IsTextTrimmed
{
get
{
return ( bool )GetValue( IsTextTrimmedProperty );
}
private set
{
SetValue( IsTextTrimmedProperty, value );
}
}
private static void OnIsTextTrimmedChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
var textBlock = d as TrimmedTextBlock;
if( textBlock != null )
{
textBlock.OnIsTextTrimmedChanged( ( bool )e.OldValue, ( bool )e.NewValue );
}
}
private void OnIsTextTrimmedChanged( bool oldValue, bool newValue )
{
this.ToolTip = ( newValue ) ? this.Text : null;
}
#endregion
#region Event Handler
private void TrimmedTextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
var textBlock = sender as TextBlock;
if( textBlock != null )
{
this.IsTextTrimmed = this.GetIsTextTrimmed( textBlock );
}
}
#endregion
#region Private Methods
private bool GetIsTextTrimmed( TextBlock textBlock )
{
if( textBlock == null )
return false;
if( textBlock.TextTrimming == TextTrimming.None )
return false;
if( textBlock.TextWrapping != TextWrapping.NoWrap )
return false;
var textBlockActualWidth = textBlock.ActualWidth;
textBlock.Measure( new Size( double.MaxValue, double.MaxValue ) );
var textBlockDesiredWidth = textBlock.DesiredSize.Width;
return ( textBlockActualWidth < textBlockDesiredWidth );
}
#endregion
}
}