Anybody know how to list the the attached properties that have been set on a UIElement in Silveright 3? Plenty of WPF solutions as usual!
Cheers
Anybody know how to list the the attached properties that have been set on a UIElement in Silveright 3? Plenty of WPF solutions as usual!
Cheers
The short answer is: it can't be done.
Silverlight's DependencyObject
does not have a GetLocalValueEnumerator
which enables this for WPF. In fact the only method which offers a glimmer is the ReadLocalValue
.
Hence if you are actually only interested in a specific sub-set of the properties you could try each one in turn through the ReadLocalValue
. Highly unsatisfactory for the general requirement though.
I'm curious, what would drive such a requirement in the first place?
A pretty horrible brute force brittle implementation I decided to go with was as follows: Scan through the loaded assemblies searching for dependency properties. If there was a dependency property with a corresponding Getxxx/Setxxx public static method then it was an attached property. Obviously it has lots of holes but it will do me for now.
The reason I want to get a list of the attached properties is so I can look at what attached properties are set on an object @ runtime and change them, just for debugging.
Code below:
public static List<DependencyProperty> GetAttachedProperties(Object element)
{
List<DependencyProperty> attachedProperties = new List<DependencyProperty>();
foreach (AssemblyPart ap in Deployment.Current.Parts)
{
StreamResourceInfo sri = Application.GetResourceStream(new Uri(ap.Source, UriKind.Relative));
Assembly a = new AssemblyPart().Load(sri.Stream);
GetAttachedProperties(a, attachedProperties);
}
return attachedProperties;
}
private static void GetAttachedProperties(Assembly a, List<DependencyProperty> attachedProperties)
{
foreach (var type in a.GetTypes())
{
Debug.WriteLine(type.FullName);
var dependencyProperties = type.GetFields(BindingFlags.Static | BindingFlags.Public).Where(
f => typeof (DependencyProperty).IsAssignableFrom(f.FieldType)).Select(f => f);
foreach (var dp in dependencyProperties)
{
FieldInfo info = dp;
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
Debug.WriteLine("{0} suitable dp methods found", methods.Count());
var fields = methods.Where(
m => (IsAttachedGetter(m, info) || IsAttachedSetter(m, info))).Select(
m => info).ToArray();
foreach(var field in fields)
{
try
{
Debug.WriteLine("Adding dependency property {0} from type {1}", dp.Name, type.FullName);
attachedProperties.Add((DependencyProperty)field.GetValue(null));
}
catch (Exception e)
{
Debug.WriteLine("Error getting dependency property {0} from type {1}, exception: {2}",
dp.Name, type.FullName, e);
}
}
}
}
}
private static bool IsAttachedSetter(MethodInfo methodInfo, FieldInfo info)
{
string setName = string.Format("Set{0}", info.Name.Replace("Property", string.Empty));
if(methodInfo.Name == setName)
{
var methodParams = methodInfo.GetParameters();
return methodParams.Count() == 2
&& typeof (DependencyObject).IsAssignableFrom(methodParams[0].ParameterType);
}
return false;
}
private static bool IsAttachedGetter(MethodInfo methodInfo, FieldInfo info)
{
string getName = string.Format("Get{0}", info.Name.Replace("Property", string.Empty));
if(methodInfo.Name == getName)
{
var methodParams = methodInfo.GetParameters();
return methodParams.Count() == 1 &&
methodParams[0].ParameterType.IsAssignableFrom(typeof (DependencyObject));
}
return false;
}