ObjectDataProvider
полезен, когда у вас есть один экземпляр объекта (или класс * stati c), к которому вы хотите привязаться, но вы используете ItemsControl
(ListView
), который делает вещи немного сложнее.
Вам нужен IValueConverter
. Это берет объект и «конвертирует» его, вызывая функцию и возвращая результат. Честно говоря, я ожидал, что смогу найти его с помощью Google, но не смог. Я подумал, что рано или поздно смогу использовать что-то подобное, поэтому я решил создать его. Это поддерживает любой тип объекта с любым именем функции, принимающим любое количество параметров.
public class FunctionConverter : IValueConverter
{
public string FunctionName { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.GetType().GetMethod(FunctionName).Invoke(value, (object[])parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
И вот пример того, как вы можете использовать его:
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
TestInstance = new Test();
InitializeComponent();
}
public Test TestInstance { get; set; }
}
public class Test
{
public string Foo(string bar)
{
return bar;
}
}
MainWindow.xaml:
<Grid>
<Grid.Resources>
<KHS:FunctionConverter x:Key="FuncCon" FunctionName="Foo"/>
</Grid.Resources>
<TextBlock>
<TextBlock.Text>
<Binding Path="TestInstance" Converter="{StaticResource FuncCon}">
<Binding.ConverterParameter>
<x:Array Type="sys:Object">
<sys:String>Hello World</sys:String>
</x:Array>
</Binding.ConverterParameter>
</Binding>
</TextBlock.Text>
</TextBlock>
</Grid>
Вы объявляете конвертер как ресурс, как вы это сделали с ObjectDataProvider
, и устанавливаете FunctionName
в качестве имени функции, которую вы хочу позвонить. Затем преобразователь использует MethodInfo.Invoke(Object, Object[])
для запуска этой функции и возвращает результат.
Параметры функции передаются через свойство ConverterParameter
привязки, которое позволит вам потенциально передавать различные значения для разных предметов в вашем списке. В этом примере я передаю строку "Hello World"
в функцию Foo
, которая просто возвращает именно то, что было передано.
Несколько заключительных замечаний: этот преобразователь работает только в одну сторону. Преобразователь, как указано, не проверяет null
и не обрабатывает, когда FunctionName
не найден. Использование такой привязки не позволяет получать уведомления об обновлениях, как это обеспечивает свойство зависимости.