Search code examples
c#wpfxamldata-bindingxmldataprovider

Binding XmlDataProvider Source attribute to a static function in another form?


I am trying to bind an XmlDataProvider with a Source attribute to a static function in another form.

Here's XmlDataProvider line -

<XmlDataProvider x:Key="Lang" Source="/lang/english.xml" XPath="Language/MainWindow"/>

I would like it's Source attribute to be binded to a static function called: "GetValue_UILanguage" in a form called: "Settings"


Solution

  • See this question's answer for a converter that allows you to bind to methods.

    You could probably modify it to be able to access static methods of any class as well.

    Edit: Here's a modified converter that should find the method via reflection.

    (Note: You would be better off using a markup extension instead, as you do not actually bind any value.)

    public sealed class StaticMethodToValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                var methodPath = (parameter as string).Split('.');
                if (methodPath.Length < 2) return DependencyProperty.UnsetValue;
    
                string methodName = methodPath.Last();
    
                var fullClassPath = new List<string>(methodPath);
                fullClassPath.RemoveAt(methodPath.Length - 1);
                Type targetClass = Assembly.GetExecutingAssembly().GetType(String.Join(".", fullClassPath));
    
                var methodInfo = targetClass.GetMethod(methodName, new Type[0]);
                if (methodInfo == null)
                    return value;
                return methodInfo.Invoke(null, null);
            }
            catch (Exception)
            {
                return DependencyProperty.UnsetValue;
            }
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException("MethodToValueConverter can only be used for one way conversion.");
        }
    }
    

    Usage:

    <Window.Resources>
        ...
        <local:StaticMethodToValueConverter x:Key="MethodToValueConverter"/>
        ...
    </Window.Resources>
    
    ...
    
    <ListView ItemsSource="{Binding Converter={StaticResource MethodToValueConverter}, ConverterParameter=Test.App.GetEmps}">
    ...
    

    The method in the App class:

    namespace Test
    {
        public partial class App : Application
        {
            public static Employee[] GetEmps() {...}
        }
    }
    

    I tested this and it works, it is important to use the full class path though, App.GetEmps alone would not have worked.