数据绑定到 WPF 中的方法

Posted

技术标签:

【中文标题】数据绑定到 WPF 中的方法【英文标题】:Databinding to a method in WPF 【发布时间】:2010-02-21 07:37:06 【问题描述】:

我在将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>

由于某种原因,它什么也没做。 Anyknow可以指出可能是什么原因? 这是我在设计器和运行应用程序时看到的:

当我尝试在运行时设置其他文本时会发生以下情况:

这是调试器在运行时尝试设置其他文本时给出的错误:

System.Windows.Data 错误:8:无法将值从目标保存回源。 BindingExpression:Path=MethodParameters[0]; DataItem='ObjectDataProvider' (HashCode=2207369);目标元素是'TextBox'(名称='textBox1');目标属性是“文本”(“字符串”类型)ArgumentException:“System.ArgumentException:“MS.Internal.Data.PropertyPathWorker+IListIndexerArg”类型的对象无法转换为“System.Int32”类型。 在 System.RuntimeType.TryChangeType(对象值,活页夹活页夹,CultureInfo 文化,布尔需求SpecialCast) 在 System.RuntimeType.CheckValue(对象值、Binder 活页夹、CultureInfo 文化、BindingFlags invokeAttr) 在 System.Reflection.MethodBase.CheckArguments(Object[] 参数,Binding 活页夹,BindingFlags invokeAttr,CultureInfo 文化,签名 sig) 在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder binder,Object[] 参数,CultureInfo 文化,布尔型 skipVisibilityChecks) 在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder 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(对象值)'

【问题讨论】:

您必须将想法从绑定方法更改为属性。并学习 INotifyPropertyChanged & DataContext 的概念。谷歌也有一些 MVVM 模式。 +1 提出了一个可以帮助很多不了解数据绑定的人的问题。 【参考方案1】:

虽然可以使用Binding 调用方法并获取其返回值,但这并不简单。绑定到属性以及使用绑定和更改通知的组合来获得您正在寻找的结果要简单得多

创建一个具有两个属性的类,FilenameExtensionFilename 只是一个读/写字符串属性。 Extension 是一个只读字符串属性,它的 getter 调用您尝试调用的方法。

现在让那个类实现INotifyPropertyChanged,因为如果一个属性可以在代码中改变,它需要一种方法来告诉绑定它已经这样做了。使Filename 属性的设置器通知绑定Extension 属性已更改。

Binding 添加到使用TwoWay 模式绑定到Filename 属性的TextBox。使用默认的OneWay 模式将Binding 添加到绑定到ExtensionTextBox

事件的顺序是:

    用户在绑定的TextBox 中键入新的Filename,然后按TAB。 TextBox 失去焦点。 因为Binding 的模式是TwoWay,并且它使用在目标失去焦点时更新源的默认行为,所以它就是这样做的。 Binding 通过调用 Filename 设置器更新源。 Filename 设置器引发 PropertyChangedBinding 处理 PropertyChanged,查看其参数,发现 Extension 属性已更改。 Binding 调用 Extension 属性的 getter。 Extension 属性的 getter 调用方法来确定Filename 的扩展名,并将其返回给BindingBinding 将其目标 TextBox 更新为 Extension 的新值。

这是数据绑定和 MVVM 模式的核心概念。一旦你理解了它,它就变成了第二天性,WPF 开发变得容易了大约千万倍。

【讨论】:

我正在使用 Sam 的 24 小时自学 WPF 电子书,到目前为止,我已经学到了很多东西,而且我在第 6 章(数据绑定章节)上学习了迄今为止学习 WPF 的最简单方法之一。我花了几个小时在网上寻找资源,这本书是迄今为止我为 WPF 初学者找到的最好的书。 :)【参考方案2】:

看来你需要了解一下 MVVM ,看看这篇经典文章 http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

【讨论】:

是的,但正如我在帖子中指出的那样,我们的想法是在运行时在文本框中输入您想要的内容。我知道它正在使用我在设计时在 标签内给他的字符串做他应该做的事情。【参考方案3】:

数据绑定需要在更新源时调用NotifyPropertyChanged 事件。在这种情况下,您需要将此函数调用包装在 get/set 中,如下所示:

public class FileWrapper: System.ComponentModel.INotifyPropertyChanged private string m_filename; public string FileExtension get return GetFileExtension(FileName); public string FileName get return m_filename; set m_filename = value; OnPropertyChanged("FileName"); OnPropertyChanged( "FileExtension"); public string GetFileExtension( string filename) //implementation public event System.ComponentModel.NotifyPropertyChangedEvent PropertyChanged = (a,b)=>; protected void OnPropertyChanged(string property) PropertyChanged( this, new System.ComponentModel.PropertyChangedEventArgs( property ));

【讨论】:

我要试试这段代码。但是,给定一些参数,从给定的类中运行一些方法,难道没有更简单的解决方案吗? @devoured,如果您喜欢以正确的 WPF 方式进行操作,这应该是您需要使用的代码。上面的代码并没有什么疯狂的地方,如果你学会了这一点,它将永远帮助你使用 WPF。在任何基于 MVVM 的 WPF 中,您都可以看到这一小段代码 sn-p。所以值得学习。 但这应该放在哪里呢? FileExtension 应该是 Window 的属性吗?【参考方案4】:

好的,这似乎是运行 WPF 4.0 时的一个错误,可以在 cmets here 中看到。

糟糕,我有点草率了.. 只要您为 3.5 框架(在 VS 2010 中)编译该示例,它就可以完美运行。 但是,如果您将其转换为 WPF 4.0 项目,则在编辑文本框时不再在 odp2 上调用 ObjectDataProvider 上的 WeightOnPlanet 方法。 我试图在 Binding 或 ObjectDataProvider 上找到任何新的属性——但到目前为止还没有任何结果……

在 3.5 中编译时,在这里可以正常工作。

【讨论】:

【参考方案5】:

DataContext 设置了吗?在您的代码隐藏中,您是否将 TextBlock 的值设置为“saadsas”(我只能猜测),这破坏了您的数据绑定?

【讨论】:

我编辑了我的原始帖子。基本上我在代码文件中写的所有东西都在那里。我没有设置 DataContext。事实上,我现在正在谷歌搜索 DataContext 是什么。

以上是关于数据绑定到 WPF 中的方法的主要内容,如果未能解决你的问题,请参考以下文章

WPF入门教程系列十八——WPF中的数据绑定

将枚举属性数据绑定到 WPF 中的组合框

将枚举属性数据绑定到 WPF 中的组合框

WPF DataGrid - 如何暂停数据绑定中的 UI 更新并稍后进行批量更新

WPF 数据验证中的绑定失败

数据绑定如何避免 WPF 中的递归更新?