Can I access ItemsHost of ItemsControl using reflection?
I'm creating custom ItemsControl
that is derived from DataGrid
. I need to a开发者_如何学Pythonccess ItemsHost that is the Panel
that actually holds rows of DataGrid
. I have seen som ugly tricks to do that but I consider them worse then using reflection.
So can I access ItemsHost using reflection ? And how ?
Yes I can. It is simple - I've just created property in class inheriting from DataGrid
:
protected Panel ItemsHost {
get {
return (Panel) typeof (MultiSelector).InvokeMember("ItemsHost",
BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance,
null, this, null);
}
}
It works like a charm :). I can get the value of ItemsHost
internal property of the ItemsControl
class. This way I can access any non-protected properties.
If you're a fan of @rasto's answer, but you're concerned about the performance of reflection, this implementation uses expression trees to create a strongly typed Func<ItemsControl, Panel>
. You incur the reflection cost only once. You can also wrap it up in a handy extension method...
public static class ItemsControlExtensions
{
private static readonly Lazy<Func<ItemsControl, Panel?>> getItemsHost
= new (CreateGetItemsHostLambda);
private static Func<ItemsControl, Panel?> CreateGetItemsHostLambda()
{
var parameter = Expression.Parameter(type: typeof(ItemsControl));
return Expression.Lambda<Func<ItemsControl, Panel>>(
body: Expression.Property(
expression: parameter,
property: typeof(ItemsControl).GetProperty(
name: "ItemsHost",
bindingAttr: BindingFlags.NonPublic
| BindingFlags.GetProperty
| BindingFlags.Instance
)!
),
parameter
).Compile();
}
public static Panel? GetItemsPanel(this ItemsControl itemsControl)
=> getItemsHost.Value(itemsControl);
}
精彩评论