#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
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.
 
 
 
 
 
 

154 lines
4.5 KiB

// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at" />
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Markup;
namespace ICSharpCode.Core.Presentation
{
/// <summary>
/// Custom binding to allow direct bindings of option properties to WPF controls.
/// </summary>
/// <remarks>
/// Properties accessed by this binding have to be managed by a custom
/// settings class, which contains all settings as static properties or fields.<br />
/// Do not use PropertyService directly!<br />
/// This markup extension can only be used in OptionPanels or other <br />containers implementing IOptionBindingContainer!
/// </remarks>
/// <example>
/// <code>
/// {sd:OptionBinding addin:XmlEditorAddInOptions.ShowAttributesWhenFolded}
/// </code>
/// <br />
/// Whereas 'sd' is the xml namespace of ICSharpCode.Core.Presentation.OptionBinding and 'addin'<br />
/// is the xml namespace, in which your settings class is defined.
/// </example>
public class OptionBinding : MarkupExtension
{
public string PropertyName { get; set; }
static readonly Regex regex = new Regex("^.+\\:.+\\..+$", RegexOptions.Compiled);
DependencyObject target;
DependencyProperty dp;
object propertyInfo;
public OptionBinding(string propertyName)
{
if (!regex.IsMatch(propertyName))
throw new ArgumentException("parameter must have the following format: namespace:ClassName.FieldOrProperty", "propertyName");
this.PropertyName = propertyName;
}
public override object ProvideValue(IServiceProvider provider)
{
IProvideValueTarget service = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
if (service == null)
return null;
target = service.TargetObject as DependencyObject;
dp = service.TargetProperty as DependencyProperty;
if (target == null || dp == null)
return null;
string[] name = PropertyName.Split('.');
IXamlTypeResolver typeResolver = provider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
Type t = typeResolver.Resolve(name[0]);
this.propertyInfo = t.GetProperty(name[1]);
IOptionBindingContainer container = TryFindContainer(target as FrameworkElement);
if (container == null)
throw new InvalidOperationException("This extension can be used in OptionPanels only!");
container.AddBinding(this);
try {
object result = null;
if (this.propertyInfo is PropertyInfo)
result = (propertyInfo as PropertyInfo).GetValue(null, null);
else {
this.propertyInfo = t.GetField(name[1]);
if (this.propertyInfo is FieldInfo)
result = (propertyInfo as FieldInfo).GetValue(null);
}
return ConvertOnDemand(result, dp.PropertyType);
} catch (Exception e) {
throw new Exception("Failing to convert " + dp.Name + " " + dp.PropertyType, e);
}
}
object ConvertOnDemand(object result, Type returnType)
{
if (returnType.IsInstanceOfType(result) || returnType == typeof(object))
return result;
if (returnType == typeof(string)) {
var converter = TypeDescriptor.GetConverter(result.GetType());
return converter.ConvertToString(result);
}
if (result is string) {
var converter = TypeDescriptor.GetConverter(returnType);
return converter.ConvertFromString(result as string);
}
return Convert.ChangeType(result, returnType);
}
IOptionBindingContainer TryFindContainer(FrameworkElement start)
{
if (start == null)
return null;
while (start != null && !(start is IOptionBindingContainer))
start = start.Parent as FrameworkElement;
return start as IOptionBindingContainer;
}
public bool Save()
{
object value = target.GetValue(dp);
Type returnType = null;
if (propertyInfo is PropertyInfo)
returnType = (propertyInfo as PropertyInfo).PropertyType;
if (propertyInfo is FieldInfo)
returnType = (propertyInfo as FieldInfo).FieldType;
if (returnType == null)
return false;
value = ConvertOnDemand(value, returnType);
if (propertyInfo is PropertyInfo) {
(propertyInfo as PropertyInfo).SetValue(null, value, null);
return true;
}
if (propertyInfo is FieldInfo) {
(propertyInfo as FieldInfo).SetValue(null, value);
return true;
}
return false;
}
}
}