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.
160 lines
5.2 KiB
160 lines
5.2 KiB
// <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.Windows.Media; |
|
using System.Windows.Controls; |
|
using ICSharpCode.WpfDesign.Extensions; |
|
|
|
namespace ICSharpCode.WpfDesign.Designer.Extensions |
|
{ |
|
/// <summary> |
|
/// Instance factory used to create Panel instances. |
|
/// Sets the panels Brush to a transparent brush, and modifies the panel's type descriptor so that |
|
/// the property value is reported as null when the transparent brush is used, and |
|
/// setting the Brush to null actually restores the transparent brush. |
|
/// </summary> |
|
[ExtensionFor(typeof(Panel))] |
|
public sealed class PanelInstanceFactory : CustomInstanceFactory |
|
{ |
|
Brush _transparentBrush = new SolidColorBrush(Colors.Transparent); |
|
|
|
/// <summary> |
|
/// Creates an instance of the specified type, passing the specified arguments to its constructor. |
|
/// </summary> |
|
public override object CreateInstance(Type type, params object[] arguments) |
|
{ |
|
object instance = base.CreateInstance(type, arguments); |
|
Panel panel = instance as Panel; |
|
if (panel != null) { |
|
if (panel.Background == null) { |
|
panel.Background = _transparentBrush; |
|
} |
|
TypeDescriptionProvider provider = new DummyValueInsteadOfNullTypeDescriptionProvider( |
|
TypeDescriptor.GetProvider(panel), "Background", _transparentBrush); |
|
TypeDescriptor.AddProvider(provider, panel); |
|
} |
|
return instance; |
|
} |
|
} |
|
|
|
sealed class DummyValueInsteadOfNullTypeDescriptionProvider : TypeDescriptionProvider |
|
{ |
|
// By using a TypeDescriptionProvider, we can intercept all access to the property that is |
|
// using a PropertyDescriptor. WpfDesign.XamlDom uses a PropertyDescriptor for accessing |
|
// properties (except for attached properties), so even DesignItemProperty/XamlProperty.ValueOnInstance |
|
// will report null when the actual value is the dummy value. |
|
|
|
readonly string _propertyName; |
|
readonly object _dummyValue; |
|
|
|
public DummyValueInsteadOfNullTypeDescriptionProvider(TypeDescriptionProvider existingProvider, |
|
string propertyName, object dummyValue) |
|
: base(existingProvider) |
|
{ |
|
this._propertyName = propertyName; |
|
this._dummyValue = dummyValue; |
|
} |
|
|
|
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) |
|
{ |
|
return new ShadowTypeDescriptor(this, base.GetTypeDescriptor(objectType, instance)); |
|
} |
|
|
|
sealed class ShadowTypeDescriptor : CustomTypeDescriptor |
|
{ |
|
readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; |
|
|
|
public ShadowTypeDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, |
|
ICustomTypeDescriptor existingDescriptor) |
|
: base(existingDescriptor) |
|
{ |
|
this._parent = parent; |
|
} |
|
|
|
public override PropertyDescriptorCollection GetProperties() |
|
{ |
|
return Filter(base.GetProperties()); |
|
} |
|
|
|
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) |
|
{ |
|
return Filter(base.GetProperties(attributes)); |
|
} |
|
|
|
PropertyDescriptorCollection Filter(PropertyDescriptorCollection properties) |
|
{ |
|
PropertyDescriptor property = properties[_parent._propertyName]; |
|
if (property != null) { |
|
if ((properties as System.Collections.IDictionary).IsReadOnly) { |
|
properties = new PropertyDescriptorCollection(Func.ToArray(properties)); |
|
} |
|
properties.Remove(property); |
|
properties.Add(new ShadowPropertyDescriptor(_parent, property)); |
|
} |
|
return properties; |
|
} |
|
} |
|
|
|
sealed class ShadowPropertyDescriptor : PropertyDescriptor |
|
{ |
|
readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; |
|
readonly PropertyDescriptor _baseDescriptor; |
|
|
|
public ShadowPropertyDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, |
|
PropertyDescriptor existingDescriptor) |
|
: base(existingDescriptor) |
|
{ |
|
this._parent = parent; |
|
this._baseDescriptor = existingDescriptor; |
|
} |
|
|
|
public override Type ComponentType { |
|
get { return _baseDescriptor.ComponentType; } |
|
} |
|
|
|
public override bool IsReadOnly { |
|
get { return _baseDescriptor.IsReadOnly; } |
|
} |
|
|
|
public override Type PropertyType { |
|
get { return _baseDescriptor.PropertyType; } |
|
} |
|
|
|
public override bool CanResetValue(object component) |
|
{ |
|
return _baseDescriptor.CanResetValue(component); |
|
} |
|
|
|
public override object GetValue(object component) |
|
{ |
|
object value = _baseDescriptor.GetValue(component); |
|
if (value == _parent._dummyValue) |
|
return null; |
|
else |
|
return value; |
|
} |
|
|
|
public override void ResetValue(object component) |
|
{ |
|
_baseDescriptor.SetValue(component, _parent._dummyValue); |
|
} |
|
|
|
public override void SetValue(object component, object value) |
|
{ |
|
_baseDescriptor.SetValue(component, value ?? _parent._dummyValue); |
|
} |
|
|
|
public override bool ShouldSerializeValue(object component) |
|
{ |
|
return _baseDescriptor.ShouldSerializeValue(component) |
|
&& _baseDescriptor.GetValue(component) != _parent._dummyValue; |
|
} |
|
} |
|
} |
|
}
|
|
|