Browse Source

WPF PropertyEditor

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2254 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
4cb3045791
  1. 96
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/DependencyPropertyDotButton.cs
  2. 20
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyEditor.cs
  3. 30
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyGridView.cs
  4. 65
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyNameTextBlock.cs
  5. 35
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/TypeEditors/BrushEditor.cs
  6. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs
  7. 3
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
  8. 5
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs
  9. 19
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs
  10. 73
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
  11. 6
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
  12. 53
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
  13. 51
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs
  14. 31
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItemProperty.cs
  15. 30
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/BooleanEditor.cs
  16. 42
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataProperty.cs
  17. 6
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs
  18. 111
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/EditorManager.cs
  19. 31
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/EnumEditor.cs
  20. 50
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/FallbackEditor.cs
  21. 37
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/IPropertyEditorDataSource.cs
  22. 50
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/PropertyEditorAttribute.cs
  23. 79
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/PropertyEditorBindingHelper.cs
  24. 54
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TextBoxEditor.cs
  25. 39
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TypeEditorAttribute.cs
  26. 8
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj

96
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/DependencyPropertyDotButton.cs

@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
// </file>
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
@ -18,14 +20,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -18,14 +20,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
/// </summary>
public class DependencyPropertyDotButton : ButtonBase
{
/*
/// <summary>
/// Dependency property for <see cref="DataProperty"/>.
/// </summary>
public static readonly DependencyProperty DataPropertyProperty
= DependencyProperty.Register("DataProperty", typeof(IPropertyEditorDataProperty), typeof(DependencyPropertyDotButton));
*/
/// <summary>
/// Dependency property for <see cref="Checked"/>.
/// </summary>
@ -33,21 +27,56 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -33,21 +27,56 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
= DependencyProperty.Register("Checked", typeof(bool), typeof(DependencyPropertyDotButton),
new FrameworkPropertyMetadata(false));
static DependencyPropertyDotButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DependencyPropertyDotButton), new FrameworkPropertyMetadata(typeof(DependencyPropertyDotButton)));
}
/*
/// <summary>
/// Gets/Sets the property the button is used for.
/// Creates a new DependencyPropertyDotButton instance.
/// </summary>
public DependencyPropertyDotButton()
{
}
IPropertyEditorDataProperty property;
bool isIsSetChangedEventHandlerAttached;
/// <summary>
/// Creates a new DependencyPropertyDotButton instance that binds its Checked property to the
/// data properties IsSet property.
/// </summary>
public DependencyPropertyDotButton(IPropertyEditorDataProperty property)
{
if (property == null)
throw new ArgumentNullException("property");
this.property = property;
this.Loaded += delegate {
if (!isIsSetChangedEventHandlerAttached) {
isIsSetChangedEventHandlerAttached = true;
this.property.IsSetChanged += OnIsSetChanged;
OnIsSetChanged(null, null);
}
};
this.Unloaded += delegate {
if (isIsSetChangedEventHandlerAttached) {
isIsSetChangedEventHandlerAttached = false;
this.property.IsSetChanged -= OnIsSetChanged;
}
};
OnIsSetChanged(null, null);
}
/// <summary>
/// Creates the context menu on-demand.
/// </summary>
public IPropertyEditorDataProperty DataProperty {
get { return (IPropertyEditorDataProperty)GetValue(DataPropertyProperty); }
set { SetValue(DataPropertyProperty, value); }
protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{
ContextMenu = CreateContextMenu();
base.OnContextMenuOpening(e);
}
*/
/// <summary>
/// Gets/Sets if the button looks checked.
@ -57,15 +86,48 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -57,15 +86,48 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
set { SetValue(CheckedProperty, value); }
}
void OnIsSetChanged(object sender, EventArgs e)
{
this.Checked = property.IsSet;
}
/// <summary>
/// Fires the Click event and opens the context menu.
/// </summary>
protected override void OnClick()
{
base.OnClick();
if (ContextMenu != null) {
ContextMenu.IsOpen = true;
ContextMenu = CreateContextMenu();
ContextMenu.IsOpen = true;
}
internal ContextMenu CreateContextMenu()
{
ContextMenu contextMenu = new ContextMenu();
if (property.IsSet) {
contextMenu.Items.Add(CreateMenuItem("_Reset", OnResetClick));
} else {
contextMenu.Items.Add(CreateMenuItem("_Copy to local", OnCopyToLocalClick));
}
return contextMenu;
}
MenuItem CreateMenuItem(string title, RoutedEventHandler handler)
{
MenuItem item = new MenuItem();
item.Header = title;
item.Click += handler;
return item;
}
void OnResetClick(object sender, RoutedEventArgs e)
{
property.IsSet = false;
}
void OnCopyToLocalClick(object sender, RoutedEventArgs e)
{
property.IsSet = true;
}
}
}

20
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyEditor.cs

@ -51,10 +51,6 @@ namespace ICSharpCode.WpfDesign.Designer @@ -51,10 +51,6 @@ namespace ICSharpCode.WpfDesign.Designer
Debug.WriteLine(ex.ToString());
throw;
}
PropertyEditorCategoryView v = new PropertyEditorCategoryView();
v.Header = "Titel";
v.Content = "Inhalt";
contentStackPanel.Children.Add(v);
}
/// <summary>
@ -66,7 +62,7 @@ namespace ICSharpCode.WpfDesign.Designer @@ -66,7 +62,7 @@ namespace ICSharpCode.WpfDesign.Designer
}
/// <summary>
/// Is raised when the object being edited changes.
/// Is raised when the value of the <see cref="EditedObject"/> property changes.
/// </summary>
public event EventHandler EditedObjectChanged;
@ -101,6 +97,9 @@ namespace ICSharpCode.WpfDesign.Designer @@ -101,6 +97,9 @@ namespace ICSharpCode.WpfDesign.Designer
List<PropertyEditorCategoryView> categories = new List<PropertyEditorCategoryView>();
foreach (IPropertyEditorDataProperty p in Linq.Sort(dataSource.Properties, ComparePropertyNames)) {
if (p.Name == "Name") {
continue;
}
PropertyEditorCategoryView cv = GetOrCreateCategory(categories, p.Category);
PropertyGridView grid = (PropertyGridView)cv.Content;
grid.AddProperty(p);
@ -120,7 +119,9 @@ namespace ICSharpCode.WpfDesign.Designer @@ -120,7 +119,9 @@ namespace ICSharpCode.WpfDesign.Designer
return p1.Name.CompareTo(p2.Name);
}
static PropertyEditorCategoryView GetOrCreateCategory(List<PropertyEditorCategoryView> categories, string category)
HashSet<string> expandedCategories = new HashSet<string>();
PropertyEditorCategoryView GetOrCreateCategory(List<PropertyEditorCategoryView> categories, string category)
{
foreach (PropertyEditorCategoryView c in categories) {
if (c.Header.ToString() == category)
@ -129,6 +130,13 @@ namespace ICSharpCode.WpfDesign.Designer @@ -129,6 +130,13 @@ namespace ICSharpCode.WpfDesign.Designer
PropertyEditorCategoryView newCategory = new PropertyEditorCategoryView();
newCategory.Header = category;
newCategory.Content = new PropertyGridView();
newCategory.IsExpanded = expandedCategories.Contains(category);
newCategory.Expanded += delegate {
expandedCategories.Add(category);
};
newCategory.Collapsed += delegate {
expandedCategories.Remove(category);
};
categories.Add(newCategory);
return newCategory;
}

30
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyGridView.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Data;
using System.Windows.Controls;
using ICSharpCode.WpfDesign.PropertyEditor;
@ -31,9 +32,9 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -31,9 +32,9 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
this.ColumnDefinitions.Add(new ColumnDefinition());
this.ColumnDefinitions.Add(new ColumnDefinition());
this.ColumnDefinitions.Add(new ColumnDefinition());
this.ColumnDefinitions[0].Width = new GridLength(0.45, GridUnitType.Star);
this.ColumnDefinitions[0].Width = new GridLength(0.48, GridUnitType.Star);
this.ColumnDefinitions[0].MinWidth = 40;
this.ColumnDefinitions[1].Width = new GridLength(0.55, GridUnitType.Star);
this.ColumnDefinitions[1].Width = new GridLength(0.52, GridUnitType.Star);
this.ColumnDefinitions[2].Width = new GridLength(16);
}
@ -44,22 +45,27 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -44,22 +45,27 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
{
this.RowDefinitions.Add(new RowDefinition());
Label propertyNameLabel = new Label();
propertyNameLabel.Content = property.Name;
propertyNameLabel.HorizontalContentAlignment = HorizontalAlignment.Right;
SetRow(propertyNameLabel, this.RowDefinitions.Count - 1);
SetColumn(propertyNameLabel, 0);
this.Children.Add(propertyNameLabel);
// Column 0: name of the property
PropertyNameTextBlock propertyNameText = new PropertyNameTextBlock(property);
propertyNameText.Margin = new Thickness(0, 0, 2, 0);
SetRow(propertyNameText, this.RowDefinitions.Count - 1);
SetColumn(propertyNameText, 0);
this.Children.Add(propertyNameText);
DependencyPropertyDotButton dotButton = new DependencyPropertyDotButton();
// Column 1: the actual property editor
UIElement editor = property.CreateEditor();
SetRow(editor, this.RowDefinitions.Count - 1);
SetColumn(editor, 1);
this.Children.Add(editor);
// Column 2: a "dot" button
DependencyPropertyDotButton dotButton = new DependencyPropertyDotButton(property);
dotButton.VerticalAlignment = VerticalAlignment.Center;
dotButton.HorizontalAlignment = HorizontalAlignment.Center;
Binding binding = new Binding("IsSet");
binding.Source = property;
dotButton.SetBinding(DependencyPropertyDotButton.CheckedProperty, binding);
SetRow(dotButton, this.RowDefinitions.Count - 1);
SetColumn(dotButton, 2);
this.Children.Add(dotButton);
propertyNameText.ContextMenuProvider = dotButton;
}
}
}

65
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PropertyEditor/PropertyNameTextBlock.cs

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using ICSharpCode.WpfDesign.PropertyEditor;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
// Text block used in the first column of the PropertyGridView.
// Creates ToolTip and ContextMenu objects on-demand.
sealed class PropertyNameTextBlock : TextBlock
{
readonly IPropertyEditorDataProperty property;
readonly TextBlock toolTipTextBlock;
bool toolTipTextBlockInitialized;
internal DependencyPropertyDotButton ContextMenuProvider;
public PropertyNameTextBlock(IPropertyEditorDataProperty property)
: base(new Run(property.Name))
{
this.property = property;
this.TextAlignment = TextAlignment.Right;
this.TextTrimming = TextTrimming.CharacterEllipsis;
this.ToolTip = toolTipTextBlock = new TextBlock();
}
protected override void OnToolTipOpening(ToolTipEventArgs e)
{
CreateToolTip();
base.OnToolTipOpening(e);
}
protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{
if (ContextMenuProvider != null) {
this.ContextMenu = ContextMenuProvider.CreateContextMenu();
}
base.OnContextMenuOpening(e);
}
void CreateToolTip()
{
if (toolTipTextBlockInitialized)
return;
toolTipTextBlockInitialized = true;
toolTipTextBlock.TextAlignment = TextAlignment.Left;
toolTipTextBlock.Inlines.Add(new Bold(new Run(property.Name)));
if (property.ReturnType != null) {
toolTipTextBlock.Inlines.Add(" (" + property.ReturnType.Name + ")");
}
if (!string.IsNullOrEmpty(property.Description)) {
toolTipTextBlock.Inlines.Add(new LineBreak());
toolTipTextBlock.Inlines.Add(property.Description);
}
}
}
}

35
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/TypeEditors/BrushEditor.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using ICSharpCode.WpfDesign.PropertyEditor;
namespace ICSharpCode.WpfDesign.Designer.Controls.TypeEditors
{
/// <summary>
/// Type editor used to edit Brush properties.
/// </summary>
[TypeEditor(typeof(Brush))]
public sealed class BrushEditor : Border
{
/// <summary>
/// Creates a new BooleanEditor instance.
/// </summary>
public BrushEditor(IPropertyEditorDataProperty property)
{
this.BorderBrush = Brushes.Black;
this.BorderThickness = new Thickness(1);
SetBinding(BackgroundProperty, PropertyEditorBindingHelper.CreateBinding(this, property));
}
}
}

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/WindowClone.cs

@ -119,7 +119,8 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -119,7 +119,8 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
}
/// <summary>
/// A <see cref="CustomInstanceFactory"/> for <see cref="Window"/>.
/// A <see cref="CustomInstanceFactory"/> for <see cref="Window"/>
/// (and derived classes, unless they specify their own <see cref="CustomInstanceFactory"/>).
/// </summary>
[ExtensionFor(typeof(Window))]
public class WindowCloneExtension : CustomInstanceFactory
@ -130,7 +131,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -130,7 +131,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
public override object CreateInstance(Type type, params object[] arguments)
{
Debug.Assert(arguments.Length == 0);
Debug.Assert(type == typeof(Window));
return new WindowClone();
}
}

3
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj

@ -62,8 +62,10 @@ @@ -62,8 +62,10 @@
<Compile Include="Controls\PropertyEditor\PropertyEditor.cs" />
<Compile Include="Controls\PropertyEditor\PropertyEditorCategoryView.cs" />
<Compile Include="Controls\PropertyEditor\PropertyGridView.cs" />
<Compile Include="Controls\PropertyEditor\PropertyNameTextBlock.cs" />
<Compile Include="Controls\ResizeThumb.cs" />
<Compile Include="Controls\SingleVisualChildElement.cs" />
<Compile Include="Controls\TypeEditors\BrushEditor.cs" />
<Compile Include="Controls\WindowClone.cs" />
<Compile Include="DesignPanel.cs" />
<Compile Include="Extensions\SelectedElementRectangleExtension.cs" />
@ -86,6 +88,7 @@ @@ -86,6 +88,7 @@
<ItemGroup>
<Folder Include="Configuration" />
<Folder Include="Controls" />
<Folder Include="Controls\TypeEditors" />
<Folder Include="Controls\PropertyEditor" />
<Folder Include="Extensions" />
<Folder Include="themes" />

5
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs

@ -10,6 +10,7 @@ using System.Xml; @@ -10,6 +10,7 @@ using System.Xml;
using ICSharpCode.WpfDesign.XamlDom;
using ICSharpCode.WpfDesign.Designer.Services;
using ICSharpCode.WpfDesign.Extensions;
using ICSharpCode.WpfDesign.PropertyEditor;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
@ -42,8 +43,12 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -42,8 +43,12 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
_componentService = new XamlComponentService(this);
this.Services.AddService(typeof(IComponentService), _componentService);
EditorManager propertyGridEditorManager = new EditorManager();
this.Services.AddService(typeof(EditorManager), propertyGridEditorManager);
// register extensions from this assembly:
this.Services.ExtensionManager.RegisterAssembly(typeof(XamlDesignContext).Assembly);
propertyGridEditorManager.RegisterAssembly(typeof(XamlDesignContext).Assembly);
XamlParserSettings xamlParseSettings = new XamlParserSettings();
xamlParseSettings.CreateInstanceCallback = OnXamlParserCreateInstance;

19
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs

@ -5,6 +5,9 @@ @@ -5,6 +5,9 @@
// <version>$Revision$</version>
// </file>
// enable this define to test that event handlers are removed correctly
//#define EventHandlerDebugging
using System;
using System.Diagnostics;
using System.Windows;
@ -48,12 +51,24 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -48,12 +51,24 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
set { throw new NotImplementedException(); }
}
#if EventHandlerDebugging
static int totalEventHandlerCount;
#endif
/// <summary>
/// Is raised when the name of the design item changes.
/// </summary>
public override event EventHandler NameChanged {
add { Debug.WriteLine("Add event handler to " + this.Component.GetType().Name); }
remove { Debug.WriteLine("Remove event handler from " + this.Component.GetType().Name); }
add {
#if EventHandlerDebugging
Debug.WriteLine("Add event handler to " + this.Component.GetType().Name + " (handler count=" + (++totalEventHandlerCount) + ")");
#endif
}
remove {
#if EventHandlerDebugging
Debug.WriteLine("Remove event handler from " + this.Component.GetType().Name + " (handler count=" + (--totalEventHandlerCount) + ")");
#endif
}
}
public override DesignItem Parent {

73
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs

@ -5,6 +5,9 @@ @@ -5,6 +5,9 @@
// <version>$Revision$</version>
// </file>
// Turn this on to ensure event handlers on model properties are removed correctly:
#define EventHandlerDebugging
using System;
using System.Diagnostics;
using ICSharpCode.WpfDesign.XamlDom;
@ -48,6 +51,18 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -48,6 +51,18 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
get { return _property.IsCollection; }
}
public override Type ReturnType {
get { return _property.ReturnType; }
}
public override Type DeclaringType {
get { return _property.PropertyTargetType; }
}
public override System.ComponentModel.TypeConverter TypeConverter {
get { return _property.TypeConverter; }
}
public override System.Collections.Generic.IList<DesignItem> CollectionElements {
get {
throw new NotImplementedException();
@ -69,23 +84,65 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -69,23 +84,65 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
}
}
public override object ValueOnInstance {
get {
return _property.ValueOnInstance;
public override event EventHandler ValueChanged {
add {
#if EventHandlerDebugging
if (ValueChangedEventHandlers == 0) {
Debug.WriteLine("ValueChangedEventHandlers is now > 0");
}
ValueChangedEventHandlers++;
#endif
_property.ValueChanged += value;
}
set {
_property.ValueOnInstance = value;
remove {
#if EventHandlerDebugging
ValueChangedEventHandlers--;
if (ValueChangedEventHandlers == 0) {
Debug.WriteLine("ValueChangedEventHandlers reached 0");
}
#endif
_property.ValueChanged -= value;
}
}
public override object ValueOnInstance {
get { return _property.ValueOnInstance; }
set { _property.ValueOnInstance = value; }
}
public override bool IsSet {
get {
return _property.IsSet;
get { return _property.IsSet; }
}
#if EventHandlerDebugging
static int IsSetChangedEventHandlers, ValueChangedEventHandlers;
#endif
public override event EventHandler IsSetChanged {
add {
#if EventHandlerDebugging
if (IsSetChangedEventHandlers == 0) {
Debug.WriteLine("IsSetChangedEventHandlers is now > 0");
}
IsSetChangedEventHandlers++;
#endif
_property.IsSetChanged += value;
}
remove {
#if EventHandlerDebugging
IsSetChangedEventHandlers--;
if (IsSetChangedEventHandlers == 0) {
Debug.WriteLine("IsSetChangedEventHandlers reached 0");
}
#endif
_property.IsSetChanged -= value;
}
}
public override void SetValue(object value)
{
_property.ValueOnInstance = value;
XamlComponentService componentService = _designItem.ComponentService;
XamlDesignItem designItem = (XamlDesignItem)componentService.GetDesignItem(value);
@ -98,8 +155,6 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -98,8 +155,6 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
designItem = componentService.RegisterXamlComponentRecursive(val as XamlObject);
_property.PropertyValue = val;
}
_property.ValueOnInstance = value;
}
public override void Reset()

6
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs

@ -10,6 +10,7 @@ using System.ComponentModel; @@ -10,6 +10,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;
using System.Xml;
@ -280,7 +281,10 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -280,7 +281,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
MethodInfo getMethod = elementType.GetMethod("Get" + propertyName, BindingFlags.Public | BindingFlags.Static);
MethodInfo setMethod = elementType.GetMethod("Set" + propertyName, BindingFlags.Public | BindingFlags.Static);
if (getMethod != null && setMethod != null) {
return new XamlAttachedPropertyInfo(getMethod, setMethod, propertyName);
FieldInfo field = elementType.GetField(propertyName + "Property", BindingFlags.Public | BindingFlags.Static);
if (field != null && field.FieldType == typeof(DependencyProperty)) {
return new XamlDependencyPropertyInfo((DependencyProperty)field.GetValue(null), true);
}
}
return null;
}

53
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

@ -73,6 +73,20 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -73,6 +73,20 @@ namespace ICSharpCode.WpfDesign.XamlDom
get { return propertyInfo.TargetType; }
}
/// <summary>
/// Gets the return type of the property.
/// </summary>
public Type ReturnType {
get { return propertyInfo.ReturnType; }
}
/// <summary>
/// Gets the type converter used to convert property values to/from string.
/// </summary>
public TypeConverter TypeConverter {
get { return propertyInfo.TypeConverter; }
}
/// <summary>
/// Gets the value of the property. Can be null if the property is a collection property.
/// </summary>
@ -82,10 +96,21 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -82,10 +96,21 @@ namespace ICSharpCode.WpfDesign.XamlDom
if (IsCollection)
throw new InvalidOperationException();
Reset();
bool wasSet = this.IsSet;
ResetInternal();
propertyValue = value;
propertyValue.AddNodeTo(this);
propertyValue.ParentProperty = this;
if (!wasSet) {
if (IsSetChanged != null) {
IsSetChanged(this, EventArgs.Empty);
}
}
if (ValueChanged != null) {
ValueChanged(this, EventArgs.Empty);
}
}
}
@ -129,10 +154,36 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -129,10 +154,36 @@ namespace ICSharpCode.WpfDesign.XamlDom
get { return propertyValue != null || collectionElements != null; }
}
/// <summary>
/// Occurs when the value of the IsSet property has changed.
/// </summary>
public event EventHandler IsSetChanged;
/// <summary>
/// Occurs when the value of the property has changed.
/// </summary>
public event EventHandler ValueChanged;
/// <summary>
/// Resets the properties value.
/// </summary>
public void Reset()
{
if (IsSet) {
propertyInfo.ResetValue(parentObject.Instance);
ResetInternal();
if (IsSetChanged != null) {
IsSetChanged(this, EventArgs.Empty);
}
if (ValueChanged != null) {
ValueChanged(this, EventArgs.Empty);
}
}
}
void ResetInternal()
{
if (propertyValue != null) {
propertyValue.RemoveNodeFromParent();

51
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlPropertyInfo.cs

@ -6,10 +6,12 @@ @@ -6,10 +6,12 @@
// </file>
using System;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;
namespace ICSharpCode.WpfDesign.XamlDom
@ -22,8 +24,10 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -22,8 +24,10 @@ namespace ICSharpCode.WpfDesign.XamlDom
{
public abstract object GetValue(object instance);
public abstract void SetValue(object instance, object value);
public abstract void ResetValue(object instance);
public abstract TypeConverter TypeConverter { get; }
public abstract Type TargetType { get; }
public abstract Type ReturnType { get; }
public abstract string Name { get; }
public abstract string FullyQualifiedName { get; }
public abstract bool IsAttached { get; }
@ -31,41 +35,44 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -31,41 +35,44 @@ namespace ICSharpCode.WpfDesign.XamlDom
internal abstract void AddValue(object collectionInstance, XamlPropertyValue newElement);
}
internal sealed class XamlAttachedPropertyInfo : XamlPropertyInfo
internal class XamlDependencyPropertyInfo : XamlPropertyInfo
{
MethodInfo _getMethod;
MethodInfo _setMethod;
string _name;
readonly DependencyProperty property;
readonly bool isAttached;
public XamlAttachedPropertyInfo(MethodInfo getMethod, MethodInfo setMethod, string name)
public XamlDependencyPropertyInfo(DependencyProperty property, bool isAttached)
{
this._getMethod = getMethod;
this._setMethod = setMethod;
this._name = name;
Debug.Assert(property != null);
this.property = property;
this.isAttached = isAttached;
}
public override TypeConverter TypeConverter {
get {
return TypeDescriptor.GetConverter(_getMethod.ReturnType);
return TypeDescriptor.GetConverter(this.ReturnType);
}
}
public override string FullyQualifiedName {
get {
return _getMethod.DeclaringType.FullName + "." + _name;
return this.TargetType.FullName + "." + this.Name;
}
}
public override Type TargetType {
get { return _getMethod.DeclaringType; }
get { return property.OwnerType; }
}
public override Type ReturnType {
get { return property.PropertyType; }
}
public override string Name {
get { return _name; }
get { return property.Name; }
}
public override bool IsAttached {
get { return true; }
get { return isAttached; }
}
public override bool IsCollection {
@ -74,12 +81,17 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -74,12 +81,17 @@ namespace ICSharpCode.WpfDesign.XamlDom
public override object GetValue(object instance)
{
return _getMethod.Invoke(null, new object[] { instance });
return ((DependencyObject)instance).GetValue(property);
}
public override void SetValue(object instance, object value)
{
_setMethod.Invoke(null, new object[] { instance, value });
((DependencyObject)instance).SetValue(property, value);
}
public override void ResetValue(object instance)
{
((DependencyObject)instance).ClearValue(property);
}
internal override void AddValue(object collectionInstance, XamlPropertyValue newElement)
@ -107,6 +119,15 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -107,6 +119,15 @@ namespace ICSharpCode.WpfDesign.XamlDom
_propertyDescriptor.SetValue(instance, value);
}
public override void ResetValue(object instance)
{
_propertyDescriptor.ResetValue(instance);
}
public override Type ReturnType {
get { return _propertyDescriptor.PropertyType; }
}
public override Type TargetType {
get { return _propertyDescriptor.ComponentType; }
}

31
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItemProperty.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
namespace ICSharpCode.WpfDesign
@ -25,6 +26,23 @@ namespace ICSharpCode.WpfDesign @@ -25,6 +26,23 @@ namespace ICSharpCode.WpfDesign
/// </summary>
public abstract string Name { get; }
/// <summary>
/// Gets the return type of the property.
/// </summary>
public abstract Type ReturnType { get; }
/// <summary>
/// Gets the type that declares the property.
/// </summary>
public abstract Type DeclaringType { get; }
/// <summary>
/// Gets the type converter used to convert property values to/from string.
/// </summary>
public virtual TypeConverter TypeConverter {
get { return TypeDescriptor.GetConverter(this.ReturnType); }
}
/// <summary>
/// Gets if the property represents a collection.
/// </summary>
@ -36,10 +54,16 @@ namespace ICSharpCode.WpfDesign @@ -36,10 +54,16 @@ namespace ICSharpCode.WpfDesign
public abstract IList<DesignItem> CollectionElements { get; }
/// <summary>
/// Gets the value of the property. This property returns null if the value is not set.
/// Gets the value of the property. This property returns null if the value is not set,
/// or if the value is set to a primitive value.
/// </summary>
public abstract DesignItem Value { get; }
/// <summary>
/// Is raised when the value of the property changes (by calling <see cref="SetValue"/> or <see cref="Reset"/>).
/// </summary>
public abstract event EventHandler ValueChanged;
/// <summary>
/// Gets/Sets the value of the property on the designed instance.
/// If the property is not set, this returns the default value.
@ -57,6 +81,11 @@ namespace ICSharpCode.WpfDesign @@ -57,6 +81,11 @@ namespace ICSharpCode.WpfDesign
/// </summary>
public abstract bool IsSet { get; }
/// <summary>
/// Occurs when the value of the IsSet property changes.
/// </summary>
public abstract event EventHandler IsSetChanged;
/// <summary>
/// Resets the property value to the default, possibly removing it from the list of properties.
/// </summary>

30
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/BooleanEditor.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Documents;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// Type editor used to edit bool properties.
/// </summary>
sealed class BooleanEditor : CheckBox
{
/// <summary>
/// Creates a new BooleanEditor instance.
/// </summary>
public BooleanEditor(IPropertyEditorDataProperty property)
{
SetBinding(IsCheckedProperty, PropertyEditorBindingHelper.CreateBinding(this, property));
}
}
}

42
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataProperty.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Diagnostics;
using System.Windows;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
@ -43,6 +44,10 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -43,6 +44,10 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
get { return "Description for " + property.Name; }
}
public System.ComponentModel.TypeConverter TypeConverter {
get { return property.TypeConverter; }
}
public bool IsSet {
get {
return property.IsSet;
@ -59,6 +64,11 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -59,6 +64,11 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
}
}
public event EventHandler IsSetChanged {
add { property.IsSetChanged += value; }
remove { property.IsSetChanged -= value; }
}
public object Value {
get {
return property.ValueOnInstance;
@ -68,6 +78,25 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -68,6 +78,25 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
}
}
public event EventHandler ValueChanged {
add { property.ValueChanged += value; }
remove { property.ValueChanged -= value; }
}
/// <summary>
/// Gets the type of the property value.
/// </summary>
public Type ReturnType {
get { return property.ReturnType; }
}
/// <summary>
/// Gets the type that declares the property.
/// </summary>
public Type DeclaringType {
get { return property.DeclaringType; }
}
public bool CanUseCustomExpression {
get {
return true;
@ -78,5 +107,18 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -78,5 +107,18 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
{
throw new NotImplementedException();
}
/// <summary>
/// Creates a UIElement that can edit the property value.
/// </summary>
public UIElement CreateEditor()
{
EditorManager manager = ownerDataSource.DesignItem.Services.GetService<EditorManager>();
if (manager != null) {
return manager.CreateEditor(this);
} else {
return new FallbackEditor(this);
}
}
}
}

6
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/DesignItemDataSource.cs

@ -54,6 +54,12 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -54,6 +54,12 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
return item.GetBehavior<IPropertyEditorDataSource>() ?? new DesignItemDataSource(item);
}
/// <summary>
/// Gets the design item for which this DesignItemDataSource was created.
/// </summary>
public DesignItem DesignItem {
get { return item; }
}
/// <summary>See <see cref="IPropertyEditorDataSource"/></summary>
public string Name {

111
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/EditorManager.cs

@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// Manages registered type and property editors.
/// </summary>
public sealed class EditorManager
{
// property return type => editor type
Dictionary<Type, Type> _typeEditors = new Dictionary<Type, Type>();
// property full name => editor type
Dictionary<string, Type> _propertyEditors = new Dictionary<string, Type>();
/// <summary>
/// Creates an editor for the specified property.
/// </summary>
public UIElement CreateEditor(IPropertyEditorDataProperty property)
{
return (UIElement)Activator.CreateInstance(GetEditorType(property), property);
}
/// <summary>
/// Creates the fallback editor for the specified property.
/// </summary>
public static UIElement CreateFallbackEditor(IPropertyEditorDataProperty property)
{
return (UIElement)Activator.CreateInstance(GetFallbackEditorType(property), property);
}
/// <summary>
/// Gets the type of the editor that can edit the specified property.
/// </summary>
public Type GetEditorType(IPropertyEditorDataProperty property)
{
if (property == null)
throw new ArgumentNullException("property");
Type editorType;
if (_propertyEditors.TryGetValue(property.DeclaringType.FullName + "." + property.Name, out editorType))
return editorType;
else if (_typeEditors.TryGetValue(property.ReturnType, out editorType))
return editorType;
else
return GetFallbackEditorType(property);
}
/// <summary>
/// Gets the type of the fallback editor used for the specified property.
/// </summary>
public static Type GetFallbackEditorType(IPropertyEditorDataProperty property)
{
Type returnType = property.ReturnType;
if (returnType.IsEnum) {
return typeof(EnumEditor);
} else if (returnType == typeof(bool)) {
return typeof(BooleanEditor);
} else {
TypeConverter c = property.TypeConverter;
if (c != null && c.CanConvertFrom(typeof(string)) && c.CanConvertTo(typeof(string)))
return typeof(TextBoxEditor);
else
return typeof(FallbackEditor);
}
}
/// <summary>
/// Registers property editors defined in the specified assembly.
/// </summary>
public void RegisterAssembly(Assembly assembly)
{
if (assembly == null)
throw new ArgumentNullException("assembly");
foreach (Type type in assembly.GetExportedTypes()) {
foreach (TypeEditorAttribute editorAttribute in type.GetCustomAttributes(typeof(TypeEditorAttribute), false)) {
CheckValidEditor(type);
_typeEditors[editorAttribute.SupportedPropertyType] = type;
}
foreach (PropertyEditorAttribute editorAttribute in type.GetCustomAttributes(typeof(PropertyEditorAttribute), false)) {
CheckValidEditor(type);
string propertyName = editorAttribute.PropertyDeclaringType.FullName + "." + editorAttribute.PropertyName;
_propertyEditors[propertyName] = type;
}
}
}
static readonly Type[] typeArrayWithPropertyEditorDataProperty = { typeof(IPropertyEditorDataProperty) };
static void CheckValidEditor(Type type)
{
if (!typeof(UIElement).IsAssignableFrom(type)) {
throw new DesignerException("Editor types must derive from UIElement!");
}
if (type.GetConstructor(typeArrayWithPropertyEditorDataProperty) == null) {
throw new DesignerException("Editor types must have a constructor that takes a IPropertyEditorDataProperty as argument!");
}
}
}
}

31
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/EnumEditor.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// Type editor used to edit enum properties.
/// </summary>
sealed class EnumEditor : ComboBox
{
/// <summary>
/// Creates a new EnumEditor instance.
/// </summary>
public EnumEditor(IPropertyEditorDataProperty property)
{
}
}
}

50
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/FallbackEditor.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// The type editor used when no other type editor could be found.
/// </summary>
[TypeEditor(typeof(object))]
public sealed class FallbackEditor : TextBlock
{
/// <summary>
/// Creates a new FallbackEditor instance for the specified property.
/// </summary>
public FallbackEditor(IPropertyEditorDataProperty property)
{
if (property == null)
throw new ArgumentNullException("property");
this.TextTrimming = TextTrimming.CharacterEllipsis;
if (property.IsSet) {
this.FontWeight = FontWeights.Bold;
}
object val = property.Value;
if (val == null) {
this.Text = "null";
this.FontStyle = FontStyles.Italic;
} else {
try {
this.Text = val.ToString();
} catch (Exception ex) {
this.FontWeight = FontWeights.Regular;
Inlines.Add(new Italic(new Run(ex.GetType().Name)));
Inlines.Add(" ");
Inlines.Add(ex.Message);
}
}
}
}
}

37
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/IPropertyEditorDataSource.cs

@ -9,6 +9,8 @@ using System; @@ -9,6 +9,8 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Media;
using System.Windows;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
@ -21,6 +23,11 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -21,6 +23,11 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
/// </summary>
string Name { get; set; }
/// <summary>
/// Is raised whenever the Name property changes value.
/// </summary>
event EventHandler NameChanged;
/// <summary>
/// Gets the type of the item (for display only).
/// </summary>
@ -62,6 +69,21 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -62,6 +69,21 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
/// </summary>
string Name { get; }
/// <summary>
/// Gets the type of the property value.
/// </summary>
Type ReturnType { get; }
/// <summary>
/// Gets the type that declares the property.
/// </summary>
Type DeclaringType { get; }
/// <summary>
/// Gets the type converter used to convert property values to/from string.
/// </summary>
TypeConverter TypeConverter { get; }
/// <summary>
/// Gets the description of the property.
/// </summary>
@ -74,11 +96,21 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -74,11 +96,21 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
/// </summary>
bool IsSet { get; set; }
/// <summary>
/// Is raised when the IsSet property has changed.
/// </summary>
event EventHandler IsSetChanged;
/// <summary>
/// Gets/Sets the value of the property.
/// </summary>
object Value { get; set; }
/// <summary>
/// Is raised when the Value property has changed.
/// </summary>
event EventHandler ValueChanged;
/// <summary>
/// Gets if using a custom expression is supported.
/// </summary>
@ -88,5 +120,10 @@ namespace ICSharpCode.WpfDesign.PropertyEditor @@ -88,5 +120,10 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
/// Sets a custom expression.
/// </summary>
void SetCustomExpression(string expression);
/// <summary>
/// Creates a UIElement that can edit the property value.
/// </summary>
UIElement CreateEditor();
}
}

50
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/PropertyEditorAttribute.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// Attribute to specify that the decorated class is a editor for the specified property.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false)]
public sealed class PropertyEditorAttribute : Attribute
{
readonly Type propertyDeclaringType;
readonly string propertyName;
/// <summary>
/// Creates a new PropertyEditorAttribute that specifies that the decorated class is a editor
/// for the "<paramref name="propertyDeclaringType"/>.<paramref name="propertyName"/>".
/// </summary>
public PropertyEditorAttribute(Type propertyDeclaringType, string propertyName)
{
if (propertyDeclaringType == null)
throw new ArgumentNullException("propertyDeclaringType");
if (propertyName == null)
throw new ArgumentNullException("propertyName");
this.propertyDeclaringType = propertyDeclaringType;
this.propertyName = propertyName;
}
/// <summary>
/// Gets the type that declares the property that the decorated editor supports.
/// </summary>
public Type PropertyDeclaringType {
get { return propertyDeclaringType; }
}
/// <summary>
/// Gets the name of the property that the decorated editor supports.
/// </summary>
public string PropertyName {
get { return propertyName; }
}
}
}

79
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/PropertyEditorBindingHelper.cs

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.ComponentModel;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// Provides a static method to create a binding between a dependency property
/// and a data property.
/// </summary>
public static class PropertyEditorBindingHelper
{
/// <summary>
/// Binds editor.property to dataProperty.Value.
/// </summary>
public static Binding CreateBinding(FrameworkElement editor, IPropertyEditorDataProperty dataProperty)
{
if (editor == null)
throw new ArgumentNullException("editor");
if (dataProperty == null)
throw new ArgumentNullException("dataProperty");
CustomBinding customBinding = new CustomBinding(dataProperty);
editor.Loaded += customBinding.OnLoaded;
editor.Unloaded += customBinding.OnUnloaded;
if (editor.IsLoaded) {
customBinding.OnLoaded(editor, null);
}
Binding b = new Binding("BoundValue");
b.Source = customBinding;
b.ConverterCulture = CultureInfo.InvariantCulture;
return b;
}
sealed class CustomBinding : INotifyPropertyChanged
{
readonly IPropertyEditorDataProperty dataProperty;
public CustomBinding(IPropertyEditorDataProperty dataProperty)
{
this.dataProperty = dataProperty;
}
internal void OnLoaded(object sender, RoutedEventArgs e)
{
dataProperty.ValueChanged += OnValueChanged;
}
internal void OnUnloaded(object sender, RoutedEventArgs e)
{
dataProperty.ValueChanged -= OnValueChanged;
}
public object BoundValue {
get { return dataProperty.Value; }
set { dataProperty.Value = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
void OnValueChanged(object sender, EventArgs e)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs("BoundValue"));
}
}
}
}
}

54
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TextBoxEditor.cs

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Documents;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// Type editor used to edit properties using a text box and the type's default type converter.
/// </summary>
sealed class TextBoxEditor : TextBox
{
/// <summary>
/// Creates a new TextBoxEditor instance.
/// </summary>
public TextBoxEditor(IPropertyEditorDataProperty property)
{
Binding b = PropertyEditorBindingHelper.CreateBinding(this, property);
b.Converter = new ToStringConverter(property.TypeConverter);
SetBinding(TextProperty, b);
}
sealed class ToStringConverter : IValueConverter
{
readonly TypeConverter converter;
public ToStringConverter(TypeConverter converter)
{
this.converter = converter;
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return converter.ConvertToString(null, culture, value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return converter.ConvertFromString(null, culture, (string)value);
}
}
}
}

39
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TypeEditorAttribute.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.WpfDesign.PropertyEditor
{
/// <summary>
/// Attribute to specify that the decorated class is a editor for properties with the specified
/// return type.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false)]
public sealed class TypeEditorAttribute : Attribute
{
readonly Type supportedPropertyType;
/// <summary>
/// Creates a new TypeEditorAttribute that specifies that the decorated class is a editor
/// for properties with the return type "<paramref name="supportedPropertyType"/>".
/// </summary>
public TypeEditorAttribute(Type supportedPropertyType)
{
if (supportedPropertyType == null)
throw new ArgumentNullException("supportedPropertyType");
this.supportedPropertyType = supportedPropertyType;
}
/// <summary>
/// Gets the supported property type.
/// </summary>
public Type SupportedPropertyType {
get { return supportedPropertyType; }
}
}
}

8
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj

@ -79,10 +79,18 @@ @@ -79,10 +79,18 @@
<Compile Include="Extensions\SelectionExtensionServer.cs" />
<Compile Include="HashSet.cs" />
<Compile Include="Linq.cs" />
<Compile Include="PropertyEditor\BooleanEditor.cs" />
<Compile Include="PropertyEditor\EnumEditor.cs" />
<Compile Include="PropertyEditor\DesignItemDataProperty.cs" />
<Compile Include="PropertyEditor\DesignItemDataSource.cs" />
<Compile Include="PropertyEditor\EditorManager.cs" />
<Compile Include="PropertyEditor\FallbackEditor.cs" />
<Compile Include="PropertyEditor\IPropertyEditorDataSource.cs" />
<Compile Include="PropertyEditor\MultiSelectionDataSource.cs" />
<Compile Include="PropertyEditor\TextBoxEditor.cs" />
<Compile Include="PropertyEditor\PropertyEditorAttribute.cs" />
<Compile Include="PropertyEditor\PropertyEditorBindingHelper.cs" />
<Compile Include="PropertyEditor\TypeEditorAttribute.cs" />
<Compile Include="ServiceContainer.cs" />
<Compile Include="DesignItem.cs" />
<Compile Include="Services.cs" />

Loading…
Cancel
Save