数据绑定到 WPF 中的方法
我在将 TextBox.Text
属性数据绑定到对象的方法时遇到问题。这个想法是允许用户在 TextBox
中写入文件名,然后使用 TextBlock
输出该文件的扩展名。
class GetFileInfo
{
public string GetFileExtension(string fileName)
{
return Path.GetExtension(fileName);
}
}
这是我的 XAML:
<Window.Resources>
<ObjectDataProvider x:Key="getFileInfo" MethodName="GetFileExtension" ObjectType="{x:Type local:GetFileInfo}">
<ObjectDataProvider.MethodParameters>
<sys:String>abc.text</sys:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<StackPanel>
<TextBox Name="textBox1">
<TextBox.Text>
<Binding Source="{StaticResource getFileInfo}" Path="MethodParameters[0]" BindsDirectlyToSource="True" UpdateSourceTrigger="PropertyChanged" />
</TextBox.Text>
</TextBox>
<TextBlock Name="textBlock1" Text="{Binding Source={StaticResource getFileInfo}}"/>
</StackPanel>
由于某种原因,它没有执行任何操作。有知道的可以指出可能是什么原因吗? 以下是我在设计器上以及运行应用程序时看到的内容:
这是当我尝试在运行时设置其他文本时发生的情况:
System.Windows.Data 错误:8:无法将值从目标保存回源。 BindingExpression:Path=方法参数[0]; DataItem='ObjectDataProvider' (HashCode=2207369);目标元素是“TextBox”(名称=“textBox1”);目标属性为“Text”(类型“String”)ArgumentException:“System.ArgumentException:类型为“MS.Internal.Data.PropertyPathWorker + IListIndexerArg”的对象无法转换为类型“System.Int32”。 在System.RuntimeType.TryChangeType(对象值,Binder活页夹,CultureInfo文化,布尔需要SpecialCast) 在 System.RuntimeType.CheckValue(对象值,活页夹活页夹,CultureInfo 区域性,BindingFlags invokeAttr) 在System.Reflection.MethodBase.CheckArguments(Object []参数,Binder活页夹,BindingFlags invokeAttr,CultureInfo文化,签名sig) 在System.Reflection.RuntimeMethodInfo.Invoke(对象obj,BindingFlags invokeAttr,Binder活页夹,Object []参数,CultureInfo文化,布尔skipVisibilityChecks) 在System.Reflection.RuntimeMethodInfo.Invoke(对象obj,BindingFlags invokeAttr,Binder活页夹,Object []参数,CultureInfo文化) 在System.Reflection.RuntimePropertyInfo.SetValue(对象obj,对象值,BindingFlags invokeAttr,活页夹活页夹,对象[]索引,CultureInfo文化) 在 MS.Internal.Data.PropertyPathWorker.SetValue(对象项,对象值) 在 MS.Internal.Data.ClrBindingWorker.UpdateValue(对象值) 在 System.Windows.Data.BindingExpression.UpdateSource(对象值)'
I am having trouble databinding a TextBox.Text
property to a object's method. The idea is allowing the user to write in a TextBox
a file name and then have a TextBlock
output that file's extension.
class GetFileInfo
{
public string GetFileExtension(string fileName)
{
return Path.GetExtension(fileName);
}
}
Here is my XAML:
<Window.Resources>
<ObjectDataProvider x:Key="getFileInfo" MethodName="GetFileExtension" ObjectType="{x:Type local:GetFileInfo}">
<ObjectDataProvider.MethodParameters>
<sys:String>abc.text</sys:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<StackPanel>
<TextBox Name="textBox1">
<TextBox.Text>
<Binding Source="{StaticResource getFileInfo}" Path="MethodParameters[0]" BindsDirectlyToSource="True" UpdateSourceTrigger="PropertyChanged" />
</TextBox.Text>
</TextBox>
<TextBlock Name="textBlock1" Text="{Binding Source={StaticResource getFileInfo}}"/>
</StackPanel>
For some reason it is not doing anything. Anyknow could point out what may be the reasons?
Here is what I see on the designer and when I run the application:
And here is what happens when I try setting other text at run-time:
Here is the error given by de debugger when trying to set other text at run-time:
System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=MethodParameters[0]; DataItem='ObjectDataProvider' (HashCode=2207369); target element is 'TextBox' (Name='textBox1'); target property is 'Text' (type 'String') ArgumentException:'System.ArgumentException: Object of type 'MS.Internal.Data.PropertyPathWorker+IListIndexerArg' cannot be converted to type 'System.Int32'.
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at MS.Internal.Data.PropertyPathWorker.SetValue(Object item, Object value)
at MS.Internal.Data.ClrBindingWorker.UpdateValue(Object value)
at System.Windows.Data.BindingExpression.UpdateSource(Object value)'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
虽然可以使用
Binding
来调用方法并获取其返回值,但这并不简单。绑定到属性以及使用绑定和更改通知的组合来获取您正在寻找的结果要简单得多。创建一个具有两个属性的类:
Filename
和Extension
。Filename
只是一个读/写字符串属性。Extension
是一个只读字符串属性,其 getter 会调用您尝试调用的方法。现在让该类实现 INotifyPropertyChanged,因为如果属性可以在代码中更改,则它需要一种方法来告诉绑定它已经这样做了。让
Filename
属性的 setter 通知绑定Extension
属性已更改。将
Binding
添加到TextBox
,使用TwoWay
模式绑定到Filename
属性。将Binding
添加到使用默认OneWay
模式绑定到Extension
的TextBox
。事件顺序是:
TextBox
中键入新的Filename
并按 TAB 键。TextBox
失去焦点。Binding
的模式是TwoWay
,并且它使用在目标失去焦点时更新源的默认行为,所以它就是这么做的。Binding
通过调用Filename
setter 来更新源。Filename
setter 引发PropertyChanged
。Binding
处理PropertyChanged
,查看其参数,并发现Extension
属性已更改。Binding
调用Extension
属性的 getter。Extension
属性的 getter 调用该方法来确定Filename
的扩展名,并将其返回给Binding
。Binding
使用Extension
的新值更新其目标TextBox
。这是数据绑定和 MVVM 模式的核心概念。一旦你理解了它,它就会成为你的第二天性,WPF 开发变得简单一千万倍。
While it's possible to use
Binding
to call a method and get its return value, it's not straightforward. It's much simpler to bind to properties, and to use the combination of binding and change notification to get the result you're looking for.Create a class with two properties,
Filename
andExtension
.Filename
is just a read/write string property.Extension
is a read-only string property whose getter calls the method that you're trying to call.Now make that class implement
INotifyPropertyChanged
, because if a property can change in code, it needs a way of telling the binding that it has done so. Make the setter of theFilename
property notify bindings that theExtension
property has changed.Add a
Binding
to aTextBox
that binds to theFilename
property using theTwoWay
mode. Add aBinding
to aTextBox
that binds toExtension
using the defaultOneWay
mode.The sequence of events is:
Filename
into a boundTextBox
and presses TAB.TextBox
loses focus.Binding
's mode isTwoWay
, and it's using the default behavior of updating the source when the target loses focus, that's what it does.Binding
updates the source by calling theFilename
setter.Filename
setter raisesPropertyChanged
.Binding
handlesPropertyChanged
, looks at its argument, and sees that theExtension
property has changed.Binding
calls theExtension
property's getter.Extension
property's getter calls the method to determine the extension forFilename
, and returns it to theBinding
.Binding
updates its targetTextBox
with the new value ofExtension
.This is the core concept underlying data binding and the MVVM pattern. Once you understand it, it becomes second nature, and WPF development becomes about ten million times easier.
看来你需要了解一下MVVM,看看这篇经典文章
http://msdn.microsoft.com/en-us/magazine/dd419663。 ASPX
Looks like you need to get an understanding of MVVM , check this classic article
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
数据绑定要求在更新源时调用
NotifyPropertyChanged
事件。在这种情况下,您需要将此函数调用包装在 get/set 中,如下所示:Databinding requires the
NotifyPropertyChanged
event to be called when the source is updated. In this case, you'd want to wrap this function call in a get/set like so:好吧,这似乎是运行 WPF 4.0 时的一个错误,可以在此处。
在 3.5 中编译时,它在这里工作得很好。
Ok, seems like this a bug when running WPF 4.0, as can be seen in comments here.
When compiling in 3.5, it works fine here.
DataContext
是否已设置?在您的代码隐藏中,您是否将TextBlock
的值设置为“saadsas”(我只能猜测),这破坏了您的数据绑定?Is the
DataContext
set? In your code-behind, did you set the value for yourTextBlock
to "saadsas" (I can only guess), which broke your databinding?