我需要访问组合框的非公共成员(突出显示的项目)

时间:2011-02-17 15:54:41

标签: c# combobox wpf-controls override

我正在为应用程序实现键导航,并且我希望在聚焦Combo Box时覆盖空格键功能,使其像enter键一样;像这样:

if (!cb.IsDropDownOpen)
{
  cb.IsDropDownOpen = true;
}
else
{
  cb.SelectedItem = cb.{non-public member HighlightedItem};
  cb.IsDropDownOpen = false;
}

问题是我需要获取该非公共成员的值,以便我可以设置所选值并关闭下拉列表(输入通常如何工作)。

现在的问题是:实现这一目标的最快和最轻松的方法是什么?

2 个答案:

答案 0 :(得分:17)

这是我做的一个帮助类:

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);
    }
}

答案 1 :(得分:13)

您必须使用反射来获取属性的值

PropertyInfo highlightedItemProperty = cb.GetType().GetProperties(BindingFlags.NonPublic  | BindingFlags.Instance).Single(pi => pi.Name == "HighlightedItem");
object highlightedItemValue = highlightedItemProperty.GetValue(cb, null);

要浏览所有属性或字段,请查看

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();

(你可以在调试器中全部阅读)