Init
This commit is contained in:
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user