绑定到 WPF 中的方法?
Posted
技术标签:
【中文标题】绑定到 WPF 中的方法?【英文标题】:Bind to a method in WPF? 【发布时间】:2010-10-04 20:58:03 【问题描述】:在这种情况下,如何在 WPF 中绑定到对象方法?
public class RootObject
public string Name get;
public ObservableCollection<ChildObject> GetChildren() ...
public class ChildObject
public string Name get;
XAML:
<TreeView ItemsSource="some list of RootObjects">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="x:Type data:RootObject"
ItemsSource="???">
<TextBlock Text="Binding Path=Name" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type data:ChildObject">
<TextBlock Text="Binding Path=Name" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
这里我想在树的每个RootObject
上绑定GetChildren
方法。
EDIT 绑定到 ObjectDataProvider
似乎不起作用,因为我正在绑定到项目列表,而 ObjectDataProvider
需要静态方法,或者它创建自己的方法实例并使用它。
例如,使用马特的答案,我得到:
System.Windows.Data 错误:33:ObjectDataProvider 无法创建对象;类型='RootObject'; Error='构造函数的参数错误。'
System.Windows.Data 错误:34:ObjectDataProvider:尝试调用类型上的方法失败;方法='GetChildren';类型='RootObject'; 'Error='指定的成员不能在目标上调用。' TargetException:'System.Reflection.TargetException: 非静态方法需要一个目标。
【问题讨论】:
是的,你是对的。 ObjectDataProvider 确实有一个 ObjectInstance 属性(在特定实例上调用它的方法),但我不认为它是一个依赖属性,所以你不能绑定它(AFAIK)。 是的,我尝试绑定到 ObjectInstance,发现它不是依赖属性。 无论如何我都会把我的答案留在那里,既可以为您的更新提供一些背景信息,也可以帮助其他发现此问题的人遇到足够类似的问题。 你真的需要绑定到ObjectInstance吗? (它会改变)假设您可以创建自己的更改事件处理并在代码中更新 ObjectDataProvider... 刚刚用一些源代码更新了我的答案,一年后。 【参考方案1】:另一种可能对您有用的方法是创建一个自定义的IValueConverter
,它将方法名称作为参数,以便像这样使用它:
ItemsSource="Binding
Converter=StaticResource MethodToValueConverter,
ConverterParameter='GetChildren'"
此转换器将使用反射查找并调用该方法。这要求方法没有任何参数。
以下是此类转换器来源的示例:
public sealed class MethodToValueConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
var methodName = parameter as string;
if (value==null || methodName==null)
return value;
var methodInfo = value.GetType().GetMethod(methodName, new Type[0]);
if (methodInfo==null)
return value;
return methodInfo.Invoke(value, new object[0]);
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
throw new NotSupportedException("MethodToValueConverter can only be used for one way conversion.");
以及相应的单元测试:
[Test]
public void Convert()
var converter = new MethodToValueConverter();
Assert.AreEqual("1234", converter.Convert(1234, typeof(string), "ToString", null));
Assert.AreEqual("ABCD", converter.Convert(" ABCD ", typeof(string), "Trim", null));
Assert.IsNull(converter.Convert(null, typeof(string), "ToString", null));
Assert.AreEqual("Pineapple", converter.Convert("Pineapple", typeof(string), "InvalidMethodName", null));
请注意,此转换器不强制使用 targetType
参数。
【讨论】:
嗯,...似乎是一个黑客,但我开始认为这可能是唯一的方法。这该死的肯定会是最简单的!【参考方案2】:不确定它在您的场景中效果如何,但您可以使用ObjectDataProvider
上的MethodName
属性让它调用特定方法(带有您MethodParameters
属性的特定参数)来检索其数据。
这是直接取自 MSDN 页面的 sn-p:
<Window.Resources>
<ObjectDataProvider ObjectType="x:Type local:TemperatureScale"
MethodName="ConvertTemp" x:Key="convertTemp">
<ObjectDataProvider.MethodParameters>
<system:Double>0</system:Double>
<local:TempType>Celsius</local:TempType>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
所以这是一个ObjectDataProvider
,它在TemperatureScale
类的实例上调用ConvertTemp
方法,传递两个参数(0
和TempType.Celsius
)。
【讨论】:
【参考方案3】:你必须绑定到方法吗?
你能绑定到getter是方法的属性吗?
public ObservableCollection<ChildObject> Children
get
return GetChildren();
【讨论】:
我认为 Cameron 的评论意味着他正在绑定到一个他无法添加属性的类型。 你应该避免绑定到调用方法的属性,尤其是如果方法可能长时间运行。拥有它属性的这些方法并不是一个好的设计,因为代码的使用者期望一个属性只能访问一个局部变量。 @markmnl 那么直接绑定到函数有什么意义呢?所以OP的问题对你的情况没有任何意义?【参考方案4】:除非您可以添加一个属性来调用该方法(或创建一个添加该属性的包装类),否则我知道的唯一方法是使用 ValueConverter。
【讨论】:
【参考方案5】:ObjectDataProvider 也有一个 ObjectInstance 属性,可以用来代替 ObjectType
【讨论】:
【参考方案6】:您可以使用System.ComponentModel
动态定义类型的属性(它们不是已编译元数据的一部分)。我在 WPF 中使用了这种方法来启用绑定到将其值存储在字段中的类型,因为无法绑定到字段。
ICustomTypeDescriptor
和 TypeDescriptionProvider
类型可以让您实现您想要的。根据this article:
TypeDescriptionProvider
允许您编写一个单独的类来实现ICustomTypeDescriptor
,然后将该类注册为其他类型的描述提供者。
我自己没有尝试过这种方法,但我希望它对你的情况有所帮助。
【讨论】:
【参考方案7】:要在 WPF 场景中绑定到对象的方法,您可以绑定到返回委托的属性。
【讨论】:
以上是关于绑定到 WPF 中的方法?的主要内容,如果未能解决你的问题,请参考以下文章