You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
861 lines
26 KiB
861 lines
26 KiB
/************************************************************************
|
|
|
|
Extended WPF Toolkit
|
|
|
|
Copyright (C) 2010-2012 Xceed Software Inc.
|
|
|
|
This program is provided to you under the terms of the Microsoft Public
|
|
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
|
|
|
This program can be provided to you by Xceed Software Inc. under a
|
|
proprietary commercial license agreement for use in non-Open Source
|
|
projects. The commercial version of Extended WPF Toolkit also includes
|
|
priority technical support, commercial updates, and many additional
|
|
useful WPF controls if you license Xceed Business Suite for WPF.
|
|
|
|
Visit http://xceed.com and follow @datagrid on Twitter.
|
|
|
|
**********************************************************************/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Controls.Primitives;
|
|
using System.Windows.Data;
|
|
using System.Windows.Input;
|
|
using Xceed.Wpf.Toolkit.PropertyGrid.Commands;
|
|
using System.Collections.Specialized;
|
|
using System.Windows.Media;
|
|
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
|
|
using System.Collections.ObjectModel;
|
|
|
|
namespace Xceed.Wpf.Toolkit.PropertyGrid
|
|
{
|
|
[TemplatePart( Name = PART_DragThumb, Type = typeof( Thumb ) )]
|
|
public class PropertyGrid : Control, ISupportInitialize, IPropertyParent
|
|
{
|
|
private const string PART_DragThumb = "PART_DragThumb";
|
|
|
|
#region Members
|
|
|
|
private Thumb _dragThumb;
|
|
private bool _hasPendingSelectedObjectChanged;
|
|
private int _initializationCount;
|
|
private PropertyItemCollection _properties;
|
|
private PropertyDefinitionCollection _propertyDefinitions;
|
|
private EditorDefinitionCollection _editorDefinitions;
|
|
|
|
#endregion //Members
|
|
|
|
#region Properties
|
|
|
|
#region AdvancedOptionsMenu
|
|
|
|
public static readonly DependencyProperty AdvancedOptionsMenuProperty = DependencyProperty.Register( "AdvancedOptionsMenu", typeof( ContextMenu ), typeof( PropertyGrid ), new UIPropertyMetadata( null ) );
|
|
public ContextMenu AdvancedOptionsMenu
|
|
{
|
|
get
|
|
{
|
|
return ( ContextMenu )GetValue( AdvancedOptionsMenuProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( AdvancedOptionsMenuProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //AdvancedOptionsMenu
|
|
|
|
#region AutoGenerateProperties
|
|
|
|
public static readonly DependencyProperty AutoGeneratePropertiesProperty = DependencyProperty.Register( "AutoGenerateProperties", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true, OnAutoGeneratePropertiesChanged ) );
|
|
public bool AutoGenerateProperties
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( AutoGeneratePropertiesProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( AutoGeneratePropertiesProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnAutoGeneratePropertiesChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
( ( PropertyGrid )o ).UpdateProperties( true );
|
|
}
|
|
|
|
#endregion //AutoGenerateProperties
|
|
|
|
|
|
|
|
|
|
#region ShowSummary
|
|
|
|
public static readonly DependencyProperty ShowSummaryProperty = DependencyProperty.Register( "ShowSummary", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true ) );
|
|
public bool ShowSummary
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( ShowSummaryProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( ShowSummaryProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //ShowSummary
|
|
|
|
#region EditorDefinitions
|
|
|
|
public EditorDefinitionCollection EditorDefinitions
|
|
{
|
|
get
|
|
{
|
|
return _editorDefinitions;
|
|
}
|
|
set
|
|
{
|
|
EditorDefinitionCollection oldValue = _editorDefinitions;
|
|
_editorDefinitions = value;
|
|
this.OnEditorDefinitionsChanged( oldValue, value );
|
|
}
|
|
}
|
|
|
|
protected virtual void OnEditorDefinitionsChanged( EditorDefinitionCollection oldValue, EditorDefinitionCollection newValue )
|
|
{
|
|
if( oldValue != null )
|
|
oldValue.CollectionChanged -= new NotifyCollectionChangedEventHandler( OnEditorDefinitionsCollectionChanged );
|
|
|
|
if( newValue != null )
|
|
newValue.CollectionChanged += new NotifyCollectionChangedEventHandler( OnEditorDefinitionsCollectionChanged );
|
|
|
|
UpdateProperties( true );
|
|
}
|
|
|
|
private void OnEditorDefinitionsCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
|
|
{
|
|
UpdateProperties( true );
|
|
}
|
|
|
|
#endregion //EditorDefinitions
|
|
|
|
#region Filter
|
|
|
|
public static readonly DependencyProperty FilterProperty = DependencyProperty.Register( "Filter", typeof( string ), typeof( PropertyGrid ), new UIPropertyMetadata( null, OnFilterChanged ) );
|
|
public string Filter
|
|
{
|
|
get
|
|
{
|
|
return ( string )GetValue( FilterProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( FilterProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnFilterChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
propertyGrid.OnFilterChanged( ( string )e.OldValue, ( string )e.NewValue );
|
|
}
|
|
|
|
protected virtual void OnFilterChanged( string oldValue, string newValue )
|
|
{
|
|
Properties.Filter( newValue );
|
|
}
|
|
|
|
#endregion //Filter
|
|
|
|
#region FilterWatermark
|
|
|
|
public static readonly DependencyProperty FilterWatermarkProperty = DependencyProperty.Register( "FilterWatermark", typeof( string ), typeof( PropertyGrid ), new UIPropertyMetadata( "Search" ) );
|
|
public string FilterWatermark
|
|
{
|
|
get
|
|
{
|
|
return ( string )GetValue( FilterWatermarkProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( FilterWatermarkProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //FilterWatermark
|
|
|
|
#region IsCategorized
|
|
|
|
public static readonly DependencyProperty IsCategorizedProperty = DependencyProperty.Register( "IsCategorized", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true, OnIsCategorizedChanged ) );
|
|
public bool IsCategorized
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( IsCategorizedProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( IsCategorizedProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnIsCategorizedChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
propertyGrid.OnIsCategorizedChanged( ( bool )e.OldValue, ( bool )e.NewValue );
|
|
}
|
|
|
|
protected virtual void OnIsCategorizedChanged( bool oldValue, bool newValue )
|
|
{
|
|
this.UpdateProperties( false );
|
|
this.UpdateThumb();
|
|
|
|
}
|
|
|
|
#endregion //IsCategorized
|
|
|
|
#region NameColumnWidth
|
|
|
|
public static readonly DependencyProperty NameColumnWidthProperty = DependencyProperty.Register( "NameColumnWidth", typeof( double ), typeof( PropertyGrid ), new UIPropertyMetadata( 150.0, OnNameColumnWidthChanged ) );
|
|
public double NameColumnWidth
|
|
{
|
|
get
|
|
{
|
|
return ( double )GetValue( NameColumnWidthProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( NameColumnWidthProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnNameColumnWidthChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
propertyGrid.OnNameColumnWidthChanged( ( double )e.OldValue, ( double )e.NewValue );
|
|
}
|
|
|
|
protected virtual void OnNameColumnWidthChanged( double oldValue, double newValue )
|
|
{
|
|
if( _dragThumb != null )
|
|
( ( TranslateTransform )_dragThumb.RenderTransform ).X = newValue;
|
|
}
|
|
|
|
#endregion //NameColumnWidth
|
|
|
|
#region Properties
|
|
|
|
public PropertyItemCollection Properties
|
|
{
|
|
get
|
|
{
|
|
return _properties;
|
|
}
|
|
}
|
|
|
|
#endregion //Properties
|
|
|
|
#region PropertyDefinitions
|
|
|
|
public PropertyDefinitionCollection PropertyDefinitions
|
|
{
|
|
get
|
|
{
|
|
return _propertyDefinitions;
|
|
}
|
|
set
|
|
{
|
|
PropertyDefinitionCollection oldValue = _propertyDefinitions;
|
|
_propertyDefinitions = value;
|
|
this.OnPropertyDefinitionsChanged( oldValue, value );
|
|
}
|
|
}
|
|
|
|
protected virtual void OnPropertyDefinitionsChanged( PropertyDefinitionCollection oldValue, PropertyDefinitionCollection newValue )
|
|
{
|
|
if( oldValue != null )
|
|
oldValue.CollectionChanged -= new NotifyCollectionChangedEventHandler( OnPropertyDefinitionsCollectionChanged );
|
|
|
|
if( newValue != null )
|
|
newValue.CollectionChanged += new NotifyCollectionChangedEventHandler( OnPropertyDefinitionsCollectionChanged );
|
|
|
|
UpdateProperties( true );
|
|
}
|
|
|
|
private void OnPropertyDefinitionsCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
|
|
{
|
|
UpdateProperties( true );
|
|
}
|
|
|
|
#endregion //PropertyDefinitions
|
|
|
|
#region IsReadOnly
|
|
|
|
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( false, OnIsReadOnlyChanged ) );
|
|
public bool IsReadOnly
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( IsReadOnlyProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( IsReadOnlyProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnIsReadOnlyChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
{
|
|
foreach( PropertyItem propertyItem in propertyGrid.Properties )
|
|
{
|
|
propertyItem.Editor.IsEnabled = !propertyGrid.IsReadOnly;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion //ReadOnly
|
|
|
|
#region SelectedObject
|
|
|
|
public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register( "SelectedObject", typeof( object ), typeof( PropertyGrid ), new UIPropertyMetadata( null, OnSelectedObjectChanged ) );
|
|
public object SelectedObject
|
|
{
|
|
get
|
|
{
|
|
return ( object )GetValue( SelectedObjectProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( SelectedObjectProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnSelectedObjectChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyInspector = o as PropertyGrid;
|
|
if( propertyInspector != null )
|
|
propertyInspector.OnSelectedObjectChanged( ( object )e.OldValue, ( object )e.NewValue );
|
|
}
|
|
|
|
protected virtual void OnSelectedObjectChanged( object oldValue, object newValue )
|
|
{
|
|
// We do not want to process the change now if the grid is initializing (ie. BeginInit/EndInit).
|
|
if( _initializationCount != 0 )
|
|
{
|
|
_hasPendingSelectedObjectChanged = true;
|
|
return;
|
|
}
|
|
|
|
this.UpdateProperties( true );
|
|
|
|
RaiseEvent( new RoutedPropertyChangedEventArgs<object>( oldValue, newValue, PropertyGrid.SelectedObjectChangedEvent ) );
|
|
}
|
|
|
|
#endregion //SelectedObject
|
|
|
|
#region SelectedObjectType
|
|
|
|
public static readonly DependencyProperty SelectedObjectTypeProperty = DependencyProperty.Register( "SelectedObjectType", typeof( Type ), typeof( PropertyGrid ), new UIPropertyMetadata( null, OnSelectedObjectTypeChanged ) );
|
|
public Type SelectedObjectType
|
|
{
|
|
get
|
|
{
|
|
return ( Type )GetValue( SelectedObjectTypeProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( SelectedObjectTypeProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnSelectedObjectTypeChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
propertyGrid.OnSelectedObjectTypeChanged( ( Type )e.OldValue, ( Type )e.NewValue );
|
|
}
|
|
|
|
protected virtual void OnSelectedObjectTypeChanged( Type oldValue, Type newValue )
|
|
{
|
|
}
|
|
|
|
#endregion //SelectedObjectType
|
|
|
|
#region SelectedObjectTypeName
|
|
|
|
public static readonly DependencyProperty SelectedObjectTypeNameProperty = DependencyProperty.Register( "SelectedObjectTypeName", typeof( string ), typeof( PropertyGrid ), new UIPropertyMetadata( string.Empty ) );
|
|
public string SelectedObjectTypeName
|
|
{
|
|
get
|
|
{
|
|
return ( string )GetValue( SelectedObjectTypeNameProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( SelectedObjectTypeNameProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //SelectedObjectTypeName
|
|
|
|
#region SelectedObjectName
|
|
|
|
public static readonly DependencyProperty SelectedObjectNameProperty = DependencyProperty.Register( "SelectedObjectName", typeof( string ), typeof( PropertyGrid ), new UIPropertyMetadata( string.Empty, OnSelectedObjectNameChanged, OnCoerceSelectedObjectName ) );
|
|
public string SelectedObjectName
|
|
{
|
|
get
|
|
{
|
|
return ( string )GetValue( SelectedObjectNameProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( SelectedObjectNameProperty, value );
|
|
}
|
|
}
|
|
|
|
private static object OnCoerceSelectedObjectName( DependencyObject o, object baseValue )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
{
|
|
if( (propertyGrid.SelectedObject is FrameworkElement) && ( String.IsNullOrEmpty( ( String )baseValue ) ))
|
|
return "<no name>";
|
|
}
|
|
|
|
return baseValue;
|
|
}
|
|
|
|
private static void OnSelectedObjectNameChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
propertyGrid.SelectedObjectNameChanged( ( string )e.OldValue, ( string )e.NewValue );
|
|
}
|
|
|
|
protected virtual void SelectedObjectNameChanged( string oldValue, string newValue )
|
|
{
|
|
}
|
|
|
|
#endregion //SelectedObjectName
|
|
|
|
#region SelectedPropertyItem
|
|
|
|
public static readonly DependencyProperty SelectedPropertyItemProperty = DependencyProperty.Register( "SelectedPropertyItem", typeof( PropertyItem ), typeof( PropertyGrid ), new UIPropertyMetadata( null, OnSelectedPropertyItemChanged ) );
|
|
public PropertyItem SelectedPropertyItem
|
|
{
|
|
get
|
|
{
|
|
return ( PropertyItem )GetValue( SelectedPropertyItemProperty );
|
|
}
|
|
internal set
|
|
{
|
|
SetValue( SelectedPropertyItemProperty, value );
|
|
}
|
|
}
|
|
|
|
private static void OnSelectedPropertyItemChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
|
{
|
|
PropertyGrid propertyGrid = o as PropertyGrid;
|
|
if( propertyGrid != null )
|
|
propertyGrid.OnSelectedPropertyItemChanged( ( PropertyItem )e.OldValue, ( PropertyItem )e.NewValue );
|
|
}
|
|
|
|
protected virtual void OnSelectedPropertyItemChanged( PropertyItem oldValue, PropertyItem newValue )
|
|
{
|
|
if( oldValue != null )
|
|
oldValue.IsSelected = false;
|
|
|
|
if( newValue != null )
|
|
newValue.IsSelected = true;
|
|
|
|
RaiseEvent( new RoutedPropertyChangedEventArgs<PropertyItem>( oldValue, newValue, PropertyGrid.SelectedPropertyItemChangedEvent ) );
|
|
}
|
|
|
|
#endregion //SelectedPropertyItem
|
|
|
|
#region ShowAdvancedOptions
|
|
|
|
public static readonly DependencyProperty ShowAdvancedOptionsProperty = DependencyProperty.Register( "ShowAdvancedOptions", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( false ) );
|
|
public bool ShowAdvancedOptions
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( ShowAdvancedOptionsProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( ShowAdvancedOptionsProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //ShowAdvancedOptions
|
|
|
|
#region ShowSearchBox
|
|
|
|
public static readonly DependencyProperty ShowSearchBoxProperty = DependencyProperty.Register( "ShowSearchBox", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true ) );
|
|
public bool ShowSearchBox
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( ShowSearchBoxProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( ShowSearchBoxProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //ShowSearchBox
|
|
|
|
#region ShowSortOptions
|
|
|
|
public static readonly DependencyProperty ShowSortOptionsProperty = DependencyProperty.Register( "ShowSortOptions", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true ) );
|
|
public bool ShowSortOptions
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( ShowSortOptionsProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( ShowSortOptionsProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //ShowSortOptions
|
|
|
|
#region ShowTitle
|
|
|
|
public static readonly DependencyProperty ShowTitleProperty = DependencyProperty.Register( "ShowTitle", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true ) );
|
|
public bool ShowTitle
|
|
{
|
|
get
|
|
{
|
|
return ( bool )GetValue( ShowTitleProperty );
|
|
}
|
|
set
|
|
{
|
|
SetValue( ShowTitleProperty, value );
|
|
}
|
|
}
|
|
|
|
#endregion //ShowTitle
|
|
|
|
#endregion //Properties
|
|
|
|
#region Constructors
|
|
|
|
static PropertyGrid()
|
|
{
|
|
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyGrid ), new FrameworkPropertyMetadata( typeof( PropertyGrid ) ) );
|
|
}
|
|
|
|
public PropertyGrid()
|
|
{
|
|
_properties = new PropertyItemCollection( new ObservableCollection<PropertyItem>() );
|
|
EditorDefinitions = new EditorDefinitionCollection();
|
|
PropertyDefinitions = new PropertyDefinitionCollection();
|
|
|
|
AddHandler( PropertyItem.ItemSelectionChangedEvent, new RoutedEventHandler( OnItemSelectionChanged ) );
|
|
CommandBindings.Add( new CommandBinding( PropertyGridCommands.ClearFilter, ClearFilter, CanClearFilter ) );
|
|
}
|
|
|
|
|
|
#endregion //Constructors
|
|
|
|
#region Base Class Overrides
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
base.OnApplyTemplate();
|
|
|
|
if( _dragThumb != null )
|
|
_dragThumb.DragDelta -= DragThumb_DragDelta;
|
|
_dragThumb = GetTemplateChild( PART_DragThumb ) as Thumb;
|
|
if( _dragThumb != null )
|
|
_dragThumb.DragDelta += DragThumb_DragDelta;
|
|
|
|
//Update TranslateTransform in code-behind instead of XAML to remove the
|
|
//output window error.
|
|
//When we use FindAncesstor in custom control template for binding internal elements property
|
|
//into its ancestor element, Visual Studio displays data warning messages in output window when
|
|
//binding engine meets unmatched target type during visual tree traversal though it does the proper
|
|
//binding when it receives expected target type during visual tree traversal
|
|
//ref : http://www.codeproject.com/Tips/124556/How-to-suppress-the-System-Windows-Data-Error-warn
|
|
TranslateTransform _moveTransform = new TranslateTransform();
|
|
_moveTransform.X = NameColumnWidth;
|
|
_dragThumb.RenderTransform = _moveTransform;
|
|
|
|
this.UpdateThumb();
|
|
}
|
|
|
|
protected override void OnPreviewKeyDown( KeyEventArgs e )
|
|
{
|
|
//hitting enter on textbox will update value of underlying source
|
|
if( this.SelectedPropertyItem != null && e.Key == Key.Enter && e.OriginalSource is TextBox )
|
|
{
|
|
if( !( e.OriginalSource as TextBox ).AcceptsReturn )
|
|
{
|
|
BindingExpression be = ( ( TextBox )e.OriginalSource ).GetBindingExpression( TextBox.TextProperty );
|
|
be.UpdateSource();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion //Base Class Overrides
|
|
|
|
#region Event Handlers
|
|
|
|
private void OnItemSelectionChanged( object sender, RoutedEventArgs args )
|
|
{
|
|
PropertyItem item = ( PropertyItem )args.OriginalSource;
|
|
if( item.IsSelected )
|
|
{
|
|
SelectedPropertyItem = item;
|
|
}
|
|
else
|
|
{
|
|
if( object.ReferenceEquals( item, SelectedPropertyItem ) )
|
|
{
|
|
SelectedPropertyItem = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DragThumb_DragDelta( object sender, DragDeltaEventArgs e )
|
|
{
|
|
NameColumnWidth = Math.Max( 0, NameColumnWidth + e.HorizontalChange );
|
|
}
|
|
|
|
#endregion //Event Handlers
|
|
|
|
#region Commands
|
|
|
|
private void ClearFilter( object sender, ExecutedRoutedEventArgs e )
|
|
{
|
|
Filter = String.Empty;
|
|
}
|
|
|
|
private void CanClearFilter( object sender, CanExecuteRoutedEventArgs e )
|
|
{
|
|
e.CanExecute = !String.IsNullOrEmpty( Filter );
|
|
}
|
|
|
|
#endregion //Commands
|
|
|
|
#region Methods
|
|
|
|
private void UpdateProperties( bool regenerateItems )
|
|
{
|
|
IEnumerable<PropertyItem> newProperties = null;
|
|
if( regenerateItems )
|
|
{
|
|
newProperties = this.GeneratePropertyItems( this.SelectedObject );
|
|
|
|
string defaultPropertyName = PropertyGridUtilities.GetDefaultPropertyName( this.SelectedObject );
|
|
this.SelectedPropertyItem = newProperties.FirstOrDefault( ( prop ) => prop.Name.Equals( defaultPropertyName ) );
|
|
}
|
|
|
|
Properties.Update( newProperties, IsCategorized, Filter );
|
|
}
|
|
|
|
private List<PropertyItem> GeneratePropertyItems(object instance)
|
|
{
|
|
var propertyItems = new List<PropertyItem>();
|
|
|
|
if( instance != null )
|
|
{
|
|
try
|
|
{
|
|
PropertyDescriptorCollection descriptors = PropertyGridUtilities.GetPropertyDescriptors( instance );
|
|
|
|
if( !AutoGenerateProperties )
|
|
{
|
|
List<PropertyDescriptor> specificProperties = new List<PropertyDescriptor>();
|
|
if( PropertyDefinitions != null )
|
|
{
|
|
foreach( PropertyDefinition pd in PropertyDefinitions )
|
|
{
|
|
foreach( PropertyDescriptor descriptor in descriptors )
|
|
{
|
|
if( descriptor.Name == pd.Name )
|
|
{
|
|
specificProperties.Add( descriptor );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
descriptors = new PropertyDescriptorCollection( specificProperties.ToArray() );
|
|
}
|
|
|
|
foreach( PropertyDescriptor descriptor in descriptors )
|
|
{
|
|
if( descriptor.IsBrowsable )
|
|
propertyItems.Add( PropertyGridUtilities.CreatePropertyItem( descriptor, this ) );
|
|
}
|
|
}
|
|
catch( Exception )
|
|
{
|
|
//TODO: handle this some how
|
|
}
|
|
}
|
|
|
|
return propertyItems;
|
|
}
|
|
|
|
private void UpdateThumb()
|
|
{
|
|
if( _dragThumb != null )
|
|
{
|
|
if( IsCategorized )
|
|
_dragThumb.Margin = new Thickness( 6, 0, 0, 0 );
|
|
else
|
|
_dragThumb.Margin = new Thickness( -1, 0, 0, 0 );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates all property values in the PropertyGrid with the data from the SelectedObject
|
|
/// </summary>
|
|
public void Update()
|
|
{
|
|
foreach( var item in Properties )
|
|
{
|
|
BindingOperations.GetBindingExpressionBase( item, PropertyItem.ValueProperty ).UpdateTarget();
|
|
}
|
|
}
|
|
|
|
#endregion //Methods
|
|
|
|
#region Events
|
|
|
|
public static readonly RoutedEvent PropertyValueChangedEvent = EventManager.RegisterRoutedEvent( "PropertyValueChanged", RoutingStrategy.Bubble, typeof( PropertyValueChangedEventHandler ), typeof( PropertyGrid ) );
|
|
public event PropertyValueChangedEventHandler PropertyValueChanged
|
|
{
|
|
add
|
|
{
|
|
AddHandler( PropertyValueChangedEvent, value );
|
|
}
|
|
remove
|
|
{
|
|
RemoveHandler( PropertyValueChangedEvent, value );
|
|
}
|
|
}
|
|
|
|
public static readonly RoutedEvent SelectedPropertyItemChangedEvent = EventManager.RegisterRoutedEvent( "SelectedPropertyItemChanged", RoutingStrategy.Bubble, typeof( RoutedPropertyChangedEventHandler<PropertyItem> ), typeof( PropertyGrid ) );
|
|
public event RoutedPropertyChangedEventHandler<PropertyItem> SelectedPropertyItemChanged
|
|
{
|
|
add
|
|
{
|
|
AddHandler( SelectedPropertyItemChangedEvent, value );
|
|
}
|
|
remove
|
|
{
|
|
RemoveHandler( SelectedPropertyItemChangedEvent, value );
|
|
}
|
|
}
|
|
|
|
public static readonly RoutedEvent SelectedObjectChangedEvent = EventManager.RegisterRoutedEvent( "SelectedObjectChanged", RoutingStrategy.Bubble, typeof( RoutedPropertyChangedEventHandler<object> ), typeof( PropertyGrid ) );
|
|
public event RoutedPropertyChangedEventHandler<object> SelectedObjectChanged
|
|
{
|
|
add
|
|
{
|
|
AddHandler( SelectedObjectChangedEvent, value );
|
|
}
|
|
remove
|
|
{
|
|
RemoveHandler( SelectedObjectChangedEvent, value );
|
|
}
|
|
}
|
|
|
|
#endregion //Events
|
|
|
|
#region Interfaces
|
|
|
|
#region ISupportInitialize Members
|
|
|
|
public override void BeginInit()
|
|
{
|
|
base.BeginInit();
|
|
_initializationCount++;
|
|
}
|
|
|
|
public override void EndInit()
|
|
{
|
|
base.EndInit();
|
|
if( --_initializationCount == 0 )
|
|
{
|
|
ProcessInitializationParameters();
|
|
}
|
|
}
|
|
|
|
private void ProcessInitializationParameters()
|
|
{
|
|
if( _hasPendingSelectedObjectChanged )
|
|
{
|
|
//This will update SelectedObject, Type, Name based on the actual config.
|
|
this.UpdateProperties( true );
|
|
_hasPendingSelectedObjectChanged = false;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IPropertyParent Members
|
|
|
|
bool IPropertyParent.IsReadOnly
|
|
{
|
|
get { return this.IsReadOnly; }
|
|
}
|
|
|
|
object IPropertyParent.ValueInstance
|
|
{
|
|
get { return this.SelectedObject; }
|
|
}
|
|
|
|
EditorDefinitionCollection IPropertyParent.EditorDefinitions
|
|
{
|
|
get { return this.EditorDefinitions; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
}
|
|
|
|
public delegate void PropertyValueChangedEventHandler( object sender, PropertyValueChangedEventArgs e );
|
|
public class PropertyValueChangedEventArgs : RoutedEventArgs
|
|
{
|
|
public object NewValue
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
public object OldValue
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public PropertyValueChangedEventArgs( RoutedEvent routedEvent, object source, object oldValue, object newValue )
|
|
: base( routedEvent, source )
|
|
{
|
|
NewValue = newValue;
|
|
OldValue = oldValue;
|
|
}
|
|
}
|
|
}
|
|
|