1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
| using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
using System.Diagnostics;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Input;
namespace WpfMentor.CommandParameterBindings
{
public class DataResource : Freezable
{
/// <summary>
/// Identifies the <see cref="BindingTarget"/> dependency property.
/// </summary>
/// <value>
/// The identifier for the <see cref="BindingTarget"/> dependency property.
/// </value>
public static readonly DependencyProperty BindingTargetProperty = DependencyProperty.Register("BindingTarget", typeof(object), typeof(DataResource), new UIPropertyMetadata(null));
/// <summary>
/// Initializes a new instance of the <see cref="DataResource"/> class.
/// </summary>
public DataResource()
{
}
/// <summary>
/// Gets or sets the binding target.
/// </summary>
/// <value>The binding target.</value>
public object BindingTarget
{
get { return (object)GetValue(BindingTargetProperty); }
set { SetValue(BindingTargetProperty, value); }
}
/// <summary>
/// Creates an instance of the specified type using that type's default constructor.
/// </summary>
/// <returns>
/// A reference to the newly created object.
/// </returns>
protected override Freezable CreateInstanceCore()
{
return (Freezable)Activator.CreateInstance(GetType());
}
/// <summary>
/// Makes the instance a clone (deep copy) of the specified <see cref="Freezable"/>
/// using base (non-animated) property values.
/// </summary>
/// <param name="sourceFreezable">
/// The object to clone.
/// </param>
protected sealed override void CloneCore(Freezable sourceFreezable)
{
base.CloneCore(sourceFreezable);
}
}
public class DataResourceBindingExtension : MarkupExtension
{
private object mTargetObject;
private object mTargetProperty;
private DataResource mDataResouce;
/// <summary>
/// Gets or sets the data resource.
/// </summary>
/// <value>The data resource.</value>
public DataResource DataResource
{
get
{
return mDataResouce;
}
set
{
if (mDataResouce != value)
{
if (mDataResouce != null)
{
mDataResouce.Changed -= DataResource_Changed;
}
mDataResouce = value;
if (mDataResouce != null)
{
mDataResouce.Changed += DataResource_Changed;
}
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="DataResourceBindingExtension"/> class.
/// </summary>
public DataResourceBindingExtension()
{
}
/// <summary>
/// When implemented in a derived class, returns an object that is set as the value of the target property for this markup extension.
/// </summary>
/// <param name="serviceProvider">Object that can provide services for the markup extension.</param>
/// <returns>
/// The object value to set on the property where the extension is applied.
/// </returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
mTargetObject = target.TargetObject;
mTargetProperty = target.TargetProperty;
// mTargetProperty can be null when this is called in the Designer.
Debug.Assert(mTargetProperty != null || DesignerProperties.GetIsInDesignMode(new DependencyObject()));
if (DataResource.BindingTarget == null && mTargetProperty != null)
{
PropertyInfo propInfo = mTargetProperty as PropertyInfo;
if (propInfo != null)
{
try
{
// extra support for commands here. Some classes don't allow a null
// command for example InputBinding. In this case we use a dummy
// command (NullCommand) instead of setting a null value.
if ( propInfo.PropertyType.IsAssignableFrom(typeof( ICommand ) ))
{
return new NullCommand();
}
return Activator.CreateInstance(propInfo.PropertyType);
}
catch (MissingMethodException)
{
// there isn't a default constructor
}
}
DependencyProperty depProp = mTargetProperty as DependencyProperty;
if (depProp != null)
{
DependencyObject depObj = (DependencyObject)mTargetObject;
return depObj.GetValue(depProp);
}
}
return DataResource.BindingTarget;
}
private void DataResource_Changed(object sender, EventArgs e)
{
// Ensure that the bound object is updated when DataResource changes.
DataResource dataResource = (DataResource)sender;
DependencyProperty depProp = mTargetProperty as DependencyProperty;
if (depProp != null)
{
DependencyObject depObj = (DependencyObject)mTargetObject;
object value = Convert(dataResource.BindingTarget, depProp.PropertyType);
depObj.SetValue(depProp, value);
}
else
{
PropertyInfo propInfo = mTargetProperty as PropertyInfo;
if (propInfo != null)
{
object value = Convert(dataResource.BindingTarget, propInfo.PropertyType);
// extra support for commands here. Some classes don't allow a null
// command for example InputBinding. In this case we use a dummy
// command (NullCommand) instead of setting a null value.
if (value == null && propInfo.PropertyType.IsAssignableFrom( typeof( ICommand ) ) )
{
value = new NullCommand();
}
propInfo.SetValue(mTargetObject, value, new object[0]);
}
}
}
private object Convert(object obj, Type toType)
{
try
{
return System.Convert.ChangeType(obj, toType);
}
catch (InvalidCastException)
{
return obj;
}
}
private class NullCommand : ICommand
{
#region ICommand Members
public bool CanExecute( object parameter )
{
return false;
}
public event EventHandler CanExecuteChanged;
public void Execute( object parameter )
{
}
#endregion
}
}
} |
Partager