I am implementing Key Navigation for an application and I want to override the space key functionality when a Combo Box is focused such that it acts like an enter key; like this:
if (!cb.IsDropDownOpen)
{
cb.IsDropDownOpen = true;
}
else
{
cb.SelectedItem = cb.{non-public member HighlightedItem};
cb.IsDropDownOpen = false;
}
The problem is that I need to get the value of that non-public member so that I can set the selected value and close the drop-down (how enter would normally work).
Now the question is: What is the fastest and hassle free way of achieving this?
This is a helper class I have for doing just this:
public static class PropertyHelper
{
/// <summary>
/// Returns a _private_ Property Value from a given Object. Uses Reflection.
/// Throws a ArgumentOutOfRangeException if the Property is not found.
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is returned</param>
/// <param name="propName">Propertyname as string.</param>
/// <returns>PropertyValue</returns>
public static T GetPrivatePropertyValue<T>(this object obj, string propName)
{
if (obj == null) throw new ArgumentNullException("obj");
PropertyInfo pi = obj.GetType().GetProperty(propName,
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance);
if (pi == null)
throw new ArgumentOutOfRangeException("propName",
string.Format("Property {0} was not found in Type {1}", propName,
obj.GetType().FullName));
return (T) pi.GetValue(obj, null);
}
/// <summary>
/// Returns a private Field Value from a given Object. Uses Reflection.
/// Throws a ArgumentOutOfRangeException if the Property is not found.
/// </summary>
/// <typeparam name="T">Type of the Field</typeparam>
/// <param name="obj">Object from where the Field Value is returned</param>
/// <param name="propName">Field Name as string.</param>
/// <returns>FieldValue</returns>
public static T GetPrivateFieldValue<T>(this object obj, string propName)
{
if (obj == null) throw new ArgumentNullException("obj");
Type t = obj.GetType();
FieldInfo fi = null;
while (fi == null && t != null)
{
fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
t = t.BaseType;
}
if (fi == null)
throw new ArgumentOutOfRangeException("propName",
string.Format("Field {0} was not found in Type {1}", propName,
obj.GetType().FullName));
return (T) fi.GetValue(obj);
}
/// <summary>
/// Sets a _private_ Property Value from a given Object. Uses Reflection.
/// Throws a ArgumentOutOfRangeException if the Property is not found.
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is set</param>
/// <param name="propName">Propertyname as string.</param>
/// <param name="val">Value to set.</param>
/// <returns>PropertyValue</returns>
public static void SetPrivatePropertyValue<T>(this object obj, string propName, T val)
{
Type t = obj.GetType();
if (t.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) == null)
throw new ArgumentOutOfRangeException("propName",
string.Format("Property {0} was not found in Type {1}", propName,
obj.GetType().FullName));
t.InvokeMember(propName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty |
BindingFlags.Instance, null, obj, new object[] {val});
}
/// <summary>
/// Set a private Field Value on a given Object. Uses Reflection.
/// </summary>
/// <typeparam name="T">Type of the Field</typeparam>
/// <param name="obj">Object from where the Property Value is returned</param>
/// <param name="propName">Field name as string.</param>
/// <param name="val">the value to set</param>
/// <exception cref="ArgumentOutOfRangeException">if the Property is not found</exception>
public static void SetPrivateFieldValue<T>(this object obj, string propName, T val)
{
if (obj == null) throw new ArgumentNullException("obj");
Type t = obj.GetType();
FieldInfo fi = null;
while (fi == null && t != null)
{
fi = t.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
t = t.BaseType;
}
if (fi == null)
throw new ArgumentOutOfRangeException("propName",
string.Format("Field {0} was not found in Type {1}", propName,
obj.GetType().FullName));
fi.SetValue(obj, val);
}
}
You'd have to use reflection to get the value of the property
PropertyInfo highlightedItemProperty = cb.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).Single(pi => pi.Name == "HighlightedItem");
object highlightedItemValue = highlightedItemProperty.GetValue(cb, null);
To browse all properties or fields, also check out
var allProps = cb.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).OrderBy(pi => pi.Name).ToList();
var allFields = cb.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).OrderBy(pi => pi.Name).ToList();
(you can read through them all in the debugger)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With