Binding a static method / function to the Func <T> property in XAML
I am working on using XAML to create an object tree, and one of the nodes looks like this:
public class ExecuteMethod : INode { #region Implementation of INode public bool Evaluate() { return Function != null && Function(); } public string Name { get; set; } private string _type; public string Type { get { if (string.IsNullOrEmpty(_type)) { _type = GetType().Name; } return _type; } } #endregion public Func<bool> Function { get; set; } } My goal is very important in order to make XAML and the code behind as clean as possible, which is not the case now when I create shell properties for each function:
public static Func<bool> Func1 { get { return Method1; } } public static bool Method1() { //Do stuff here return true; } and xaml is as follows:
<Root xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="clr-namespace:XamlBT;assembly=XamlBT" xmlns:d="clr-namespace:TestBT;assembly=TestBT"> <Root.Child> <Sequence Name="sequence1" > <ExecuteMethod Name="e1.1" Function="{x:Static d:Program.Func1}" /> <Selector Name="selector1" > <ExecuteMethod Name="e2.1" Function="{x:Static d:Program.Func1}" /> </Selector> </Sequence> </Root.Child> I would like to know if there is a quick and easy way to bind methods / functions to the Func property, I'm talking about a method here is NOT the value of the executed method / function. (I might think about using some reflection magic in the valueConverter or inside the ExecuteMethod node / class, but it just seems dirty and weird) An example of how I would like the XAML to look:
<Root xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="clr-namespace:XamlBT;assembly=XamlBT" xmlns:d="clr-namespace:TestBT;assembly=TestBT"> <Root.Child> <Sequence Name="sequence1" > <ExecuteMethod Name="e1.1" Function="{x:Static d:Program.Method1}" /> <Selector Name="selector1" > <ExecuteMethod Name="e2.1" Function="{x:Static d:Program.Method1}" /> </Selector> </Sequence> </Root.Child> Thanks for any help in advance and sorry for the poor grammar of the English language, this is not my native language :)
I can come up with a couple of ways to make it cleaner, but there is no syntax for binding to what you are asking. I assume that you would be most happy to write your own markup extension so that you can look like {d:StaticMethod Program.Method1} , but you would definitely have to use reflection, but it would be trivial to cache and would look better than the converter values.
Thanks jbtule!
here's the solution if someone needs this:
[MarkupExtensionReturnType(typeof (Func<bool>))] public class StaticMethodExtension : MarkupExtension { public StaticMethodExtension(string method) { Method = method; } [ConstructorArgument("method")] public string Method { get; set; } private Func<bool> _func; #region Overrides of MarkupExtension public override object ProvideValue(IServiceProvider serviceProvider) { if (_func == null) { int index = Method.IndexOf('.'); if (index < 0) { throw new ArgumentException("MarkupExtensionBadStatic"); } string qualifiedTypeName = this.Method.Substring(0, index); if (qualifiedTypeName == string.Empty) { throw new ArgumentException("MarkupExtensionBadStatic"); } IXamlTypeResolver service = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver; if (service == null) { throw new ArgumentException("MarkupExtensionNoContext"); } var memberType = service.Resolve(qualifiedTypeName); var str = this.Method.Substring(index + 1, (this.Method.Length - index) - 1); if (str == string.Empty) { throw new ArgumentException("MarkupExtensionBadStatic"); } var reflectedFunc = memberType.GetMethod(str, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static); if (reflectedFunc != null) { if (reflectedFunc.ReturnType == typeof(bool)) { var v = Delegate.CreateDelegate(typeof(Func<bool>), reflectedFunc, true); _func = (Func<bool>) v; } } } return _func; } #endregion }