2010-08-28 42 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