2010-08-28 38 views
27

我想学习WPF,但我发现很难理解绑定,“资源”和对象创建。 我的背景是C++/MFC和C#-Winforms。初学者 - 关于WPF中绑定和资源的困惑

我的问题:

  1. 大多数我看到的例子在XAML(可在MSDN和另外两个WPF的书我读过)使用静态资源的绑定表达式。这些与静态成员有什么关系?或者这只是一个误导性的名字?当引用任何对象作为StaticResource时,它是什么时候实例化的?

  2. 至于我可以看到StaticResources与应用程序/窗/控制的“资源”部分等中定义的“东西”用
    现在,这些资源的部分都非常混乱给我。 他们究竟是什么?从我在MFC中的经验来看,这些是图标,字符串等。然而,从我看到的所有例子来看,在WPF中,这些似乎本质上是一个“倾销地”,它们可以用于各种全局对象定义在标记中(样式,数据模板等) (b)标记中的各种全局对象实例 我正确吗?这让我感到非常混乱。
    它主要包括学习XAML中的各种半DSL(用于定义样式,用于定义数据模板,用于创建对象等),并将它们粘在一起放在同一个地方。 我一直在想,如何在MFC中手动编辑资源文件(.rc)。至少在那里这些部分是分开的,每种资源的语法都比较简单。

  3. 为了解决前面两个问题:当我在Resources部分中定义一个对象实例,并且稍后从StaticResource绑定中引用它时,它的实例是什么时候? MSDN说,(在“如何:使数据可用于XAML绑定”):

一个办法可以使对象 可结合是 它定义为一个资源

但是,这不是很清楚。他们的意思是什么?他们的意思是创建?他们的意思是连接绑定子系统吗?何时该对象创建为? 从一个简单的例子中,我看到WPF似乎为它创建这个对象,当它试图附加绑定。这更令人困惑。

编辑: 经过下面karmicpuppet的澄清之后,我仍然对这是如何连接到绑定感到困惑。 假设我有我的资源:

<local:Person x:Key="MyPerson" Name="Title"/> 

(其中人是一个名为名称属性的类),然后在窗口中我有:

<TextBlock Text="{Binding Source={StaticResource MyPerson}, Path=Name}"/> 

1)这是什么呢?它是否经历了相同的步骤 - 搜索资源并将其应用于Text属性? MyPerson对象是否在创建窗口时或之后创建? 2)我是否必须使用绑定机制绑定到Name属性?我不能像上面用myBrush那样直接绑定它吗?为什么我不能做这样的事情?

<TextBlock Text="{StaticResource MyPerson, Path=Name}"/> 

它只是框架方面的近视吗?我认为我在这里失踪很大,但我似乎无法理解什么...

3)我尝试使用DynamicResource,但我对每一步我都非常困惑。 A)中加入在上面的代码我的单个窗口类一个DependencyProperty为DependencyObject(是此DependencyObject必要?)

public class SomeText : DependencyObject 
{ 
    public string Header 
    { 
     get { return (string)GetValue(HeaderProperty); } 
     set { SetValue(HeaderProperty, value); } 
    } 
    public static readonly DependencyProperty HeaderProperty = 
     DependencyProperty.Register("Header", typeof(string), typeof(SomeText), new UIPropertyMetadata(0)); 
} 

b)中添加了它的一个实例的Windows.Resources(这是必要的与DynamicResource?MSDN似乎说没有,但如果让我无法弄清楚如何做到在XAML下一步)

三)我都尝试:

Text="{Binding Source={DynamicResource HeaderText}, Path=Header}" 

这给了我一个例外,

Text="{DynamicResource HeaderText}" 

但我不明白的地方把路径Header属性。

这是我第五次尝试最近摆弄WPF,每次我都被这个看似简单的事情搞砸了。我已经阅读了2本书,并且我非常想了解MSDN文章,但是它们根本没有任何帮助。

+1

等到你发现自己需要一次性即时动画.. – Blindy 2010-08-28 16:27:03

回答

14

想想这样:所有FrameworkElements(Windows,Buttons,其他控件等)以及Application对象都包含一个资源字典。无论何时定义在XAML的资源如下所示:

<Window> 
    <Window.Resources> 
    <SolidColorBrush x:Key="myBrush" Color="Red"/> 
    <DataTemplate x:Key"myTemplate"> 
     <!--Template definition here --> 
    </DataTemplate> 
    </Window.Resources> 
</Window> 

这就像在代码中做这样的事情:

class Window 
{ 
    void Window() 
    { 
    this.Resources.Add("myBrush", new SolidColorBrush(Brushes.Red)); 
    this.Resources.Add("myTemplate", new DataTemplate()); 
    } 
} 

你可以把各种对象的资源。您希望在整个应用程序中重复使用的任何内容,都可以将其定义为资源。

现在,当你使用“{}的StaticResource”如下:

<Button Background="{StaticResource myBrush}"/> 

这就好比告诉WPF来搜索相应的“myBrush”资源,并将其应用于背景属性。 WPF将首先在Button的资源字典中搜索资源,如果未找到,将搜索它的父代,然后搜索其父代的父代,直到应用程序的资源。

“StaticResource”中的“静态”事物只是将它与其他类型的名为“DynamicResource”的资源查找区分开来。两者之间的差异在this link得到解答。

当应用于绑定时,它也以同样的方式工作。说,例如,你有以下的资源在你的XAML:

<local:Person x:Key="MyPerson" Name="Title"/> 

,并用它作为:

<TextBlock Text="{Binding Source={StaticResource MyPerson}, Path=Name}"/> 

在这种情况下,会发生什么事情是这样的:

Binding b = new Binding(); 
b.Source = FindResource("MyPerson"); 
b.Path = "Name"; 
[TextBlock].SetBinding(TextBlock.TextProperty, b); 

再次,XAML中的“{StaticResource}”标记告诉WPF搜索相应的资源并将其设置为属性的值。在这种情况下,该属性是Binding的“Source”属性。

这就是基础知识。希望你觉得这有帮助

+0

好的,谢谢,但是我仍然不清楚它是如何连接到绑定系统的。 假设我有我的资源: (其中Person是一个名为Name的属性的类) 然后在窗口中我有: 1)这是干什么用的?它是否经历了相同的步骤 - 搜索资源并将其应用于Text属性? 2)我是否必须使用绑定机制绑定到Name属性?我不能像上面用myBrush那样直接绑定它吗? – OrWhen 2010-08-28 18:02:10

+0

将上述评论移至实际问题。 因此,它*是各种“事物”的倾倒场。这只是一个等级倾倒场。大。 对我来说,感觉是这个“资源”从来没有被认为是人类可编辑的,甚至是人类可读的,但是是由工具生成的。我发现XAML是一个非常糟糕的代码替代品。还是仅仅因为我是初学者? – OrWhen 2010-08-28 18:41:15

+1

我已经更新了我的答案,包含一些关于StaticResources和Binding的内容。这回答你的第一个问题。至于你的第二个问题,那么你需要一个“Person”对象的“Name”属性,所以是的,你必须使用Binding来获得该属性。基本上,你需要两件事来设置TextBlock的Text属性:1)Person对象(可以通过“{StaticResource}”进行“搜索”),2)指定你想要的“Name”属性通过“{Binding Path = Name}”设置)。希望这是有道理的。 – ASanch 2010-08-28 18:44:00

38

首先,整体评论:

WPF很难学。这很难学,因为有几个不同的基本的新概念,你必须同时让你的头脑。那你现在遇到的斗争,是你想在一次学习至少有三个不同的事情:

  • 如何XamlReader(特别标记扩展)XAML反序列化到对象。
  • FrameworkElement的资源字典是如何工作的。
  • 数据绑定如何工作。

事情是这样的:

<TextBox Text="{Binding Source={StaticResource MyPerson}, Path=Name}"/> 

是从事(至少)三个非常不同的技术在同一时间。这些技术的设计都尽可能灵活,这只会让初学者感到困惑。有约束力的来源可以是任何东西的想法:这很难把握。标记扩展是支持递归的一种特殊的序列化格式:原理上很简单,但当你第一次开始使用真实世界的例子时有点困惑。资源字典可以包含任何东西,资源搜索算法本质上使得资源可以继承的想法:再一次,在概念上非常简单,但是当您试图找出数据绑定和XAML时很容易失去线索同一时间。

这很令人沮丧,因为概念上很简单的东西 - “我想将此控件绑定到我创建的对象的属性” - 要求您在用XAML实际表达它之前了解许多事情。

唯一的解决方法是要耐心,并确保你尽可能地理解事情的最低水平。当你看到这一点:

{StaticResource MyPerson} 

,你应该能想到,“这将调用StaticResource标记扩展处理程序,它获取使用键MyPerson当XAML反序列化从资源字典的对象。

起初是非常具有挑战性的,我一直在专业开发软件已经35年了,我发现WPF是我学到的最有挑战性的技术平台,但是所有这些东西都很难学习是因为它功能强大且灵活,而且学习它的收益是巨大的。

为了解决一对夫妇的那karmicpuppet没问题:

从我的MFC经验[资源]为图标,字符串等

这并没有改变。您仍然可以在WPF中创建资源文件,并在运行时将它们加载到对象中。有很多不同的方法可以做到这一点 - 您可以在资源编辑器中创建资源并通过Properties.Resources对象加载它们,您可以将图像文件(例如)添加到项目中,将它们编译为资源,并使用它们加载它们URI,还有很多我不知道的其他方法。

通过其资源字典可用于FrameworkElement的资源是不同的。好吧,有点。这里有一个例子:

<Window.Resources> 
    <Image x:Key="MyImage" Source="images/myimage.png"/> 
</Window.Resources> 

这将创建一个Image对象,并将其与MyImage一个键,然后您可以通过在XAML的StaticResource标记扩展引用对象,或在FindResource方法增加了Window的资源字典码。

在XAML Image元素上设置Source属性也使得XamlReader使用ResourceManager在运行时,它会创建Image对象读取从项目的编制资源的图像数据。

实际上,这远不像您第一次学习WPF时那么困惑。我从来没有获得资源,ResourceManager加载和资源存储在资源字典混合起来。

何时到底是那个物体创建的

XamlReader读取元素时,将创建由XAML元素定义的任何对象。所以这个:

<Window.Resources> 
    <local:Person x:Key="MyPerson"/> 
</Window.Resources> 

实例化一个新Person对象,并将其与MyPerson一键添加到Window的资源字典。这是完全等同于在这样的Window的后台代码:

AddResource("MyPerson", new Person()); 

那么,为什么你不只是做它在代码隐藏?两个原因:

首先,它是一致的。如果您使用XAML定义所有资源,则只需查看XAML文件即可找到您的资源。如果您在XAML和代码隐藏中定义它们,则必须查看两个地方。

其次,IDE知道您在XAML中定义的资源。如果您在XAML类型

<TextBox Text="{Binding {StaticResource MyPerson}, Path=Name}"/> 

,IDE将让你知道,如果你还没有定义,在资源字典,一种资源,其关键是MyPerson的层次结构的某个地方。但是它不知道你在代码中添加的资源,所以尽管资源在运行时可能实际上是可找到的,但IDE会将其报告为一个问题。

+0

+1很好的答案。 – crypted 2011-07-12 17:33:45

+0

这让我有些放松 - 很高兴我不是唯一一个发现wpf很难掌握的人 - 但最终真棒! – Mafii 2016-07-07 06:44:22

+0

多么了不起的答案,我刚刚开始学习wpf也使用重命名工具程序即时创建,看起来你必须有大量的耐心学习它... – Chopnut 2017-03-11 19:32:25