程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 《Programming WPF》翻譯 第4章 5.主從復合(Master-Detail)綁定

《Programming WPF》翻譯 第4章 5.主從復合(Master-Detail)綁定

編輯:關於.NET

我們已經看到綁定一個單獨的對象,還看到綁定一個單獨的對象列表。另一 種非常流行的方式是綁定多個對象列表,尤其是相關的列表。例如,如果你向用 戶顯示一個客戶列表,當他們選中其中一個客戶,就會顯示客戶的相關訂單,這 時,你就會使用主從復合綁定。

主從復合綁定是一種過濾的形式,在主頁面的列表部分,客戶452設置了過濾 器作為聯合到從頁面數據的參數,例如,客戶452的相關訂單。

到我們目前的討論為止,我們並沒有客戶和訂單這樣的模型,但是我們已經 有了家庭和人的定義,於是可以進一步形式化這些,如示例4-47

示例4-47

public class Families : ObservableCollection<Family> {}

public class Family {
  string familyName;
  public string FamilyName {
    get { return familyName; }
    set { familyName = value; }
  }

  People members;
  public People Members {
    get { return members; }
    set { members = value; }
  }
}

public class People : ObservableCollection<Person> {}

public class Person {
  string name;
  public string Name {
    get { return name; }
    set { name = value; }
  }

  int age;
  public int Age {
    get { return age; }
    set { age = value; }
  }
}

在示例4-47中,我們得到了熟悉的具有Name和Age屬性的Person類,聚合在熟 悉的People集合中。進一步,我們有Family這樣的類,具有FamilyName屬性和 People類型的Members屬性。最後,我們有一個Families集合,聚合了Family類 型的對象。換句話說,families包含著members,後者由帶有年齡和名稱的 people組成。。

你可以想象到Families,Family,People以及Person的實例如圖4-19所示。

在圖4-19中,Families集合構成了主頁面的數據,保存著Family類的實例, 每一個Family實例中持有一個People類型的Members屬性,People類型中保存著 Person這樣的數據。你可以導入這種數據結構的實例,正如示例4-48所示。

圖4-19

示例4-48

<!-- Window1.xaml -->
<?Mapping
  XmlNamespace="local" ClrNamespace="MasterDetailBinding" ?>
<Window  xmlns:local="local">
  <Window.Resources>
    <local:Families x:Key="Families">
      <local:Family FamilyName="Stooge">
        <local:Family.Members>
          <local:People>
            <local:Person Name="Larry" Age="21" />
            <local:Person Name="Moe" Age="22" />
            <local:Person Name="Curly" Age="23" />
          </local:People>
        </local:Family.Members>
      </local:Family>
      <local:Family FamilyName="Addams">
        <local:Family.Members>
          <local:People>
            <local:Person Name="Gomez" Age="135" />
            <local:Person Name="Morticia" Age="121" />
            <local:Person Name="Fester" Age="137" />
          </local:People>
        </local:Family.Members>
      </local:Family>
    </local:Families>
  </Window.Resources>

</Window>

在頂級綁定到這些數據,例如,顯示這些家庭的姓名,如示例4-49所示。

示例4-49

<!-- Window1.xaml -->
<?Mapping  ?>
<Window >
  <Window.Resources>
    <local:Families x:Key="Families"></local:Families>
  </Window.Resources>
  <Grid DataContext="{StaticResource Families}">

    <!-- Families Column -->
    <TextBlock Grid.Row="0" Grid.Column="0">Families:</TextBlock>
    <ListBox Grid.Row="1" Grid.Column="0"
      IsSynchronizedWithCurrentItem="True"
      ItemsSource="{Binding}">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <TextBlock TextContent="{Binding Path=FamilyName}" />
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
</Window>

在示例4-49中,我們在Families列(第0行)做了兩件事。第一件將標題設置 為常量“Families”字符串;第二件是形成了body主體,這是一個Family對象的 清單,位於Families集合中,現時每一個家庭的FamilyName屬性,正如圖4-20所 示。

圖4-20

圖4-20並不是一個主從復合結構,因為選中一個主頁面的家庭並不會顯示這 個家庭聯合到的詳細信息。為了這麼做,我們需要綁定到下一級,如示例4-50所 示。

示例4-50

<Grid DataContext="{StaticResource Families}">

  <!-- Families Column -->

  <!-- Members Column -->
  <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
    <TextBlock TextContent="{Binding Path=FamilyName}" />
    <TextBlock TextContent=" Family Members:" />
  </StackPanel>
  <ListBox Grid.Row="1" Grid.Column="1"
    IsSynchronizedWithCurrentItem="True"
    ItemsSource="{Binding Path=Members}" >
    <ListBox.ItemTemplate>
      <DataTemplate>
        <StackPanel Orientation="Horizontal">
          <TextBlock TextContent="{Binding Path=Name}" />
          <TextBlock TextContent=" (age: " />
          <TextBlock TextContent="{Binding Path=Age}" />
          <TextBlock TextContent=" )" />
        </StackPanel>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>

在Members列(第1列),我們也設置了標題和主體,但是這次標題綁定到當 前選中的Family對象的FamilyName。

同樣,回憶在Families列,我們的列表框的源條目通過不帶Path屬性的 Binding語句,綁定到了整個集合。然而,在從頁面中,我們想告訴數據綁定引 擎,我們想要綁定到當前選中的Family對象的Members屬性,這是一個Person對 象的列表。圖4-21顯示了主從綁定的效果。

圖4-21

但是,稍等:有點過了。主從綁定並沒有在這兩個級別停下來,根本沒有。 你可以走得盡可能深,每一個從頁面都是主頁面的下一級。為了看到這個效果, 讓我們多增加一級從頁面到我們的數據類,如示例4-51所示。

示例4-51

public class Person {
  string name;
  public string Name {
    get { return name; }
    set { name = value; }
  }

  int age;
  public int Age {
    get { return age; }
    set { age = value; }
  }

  Traits traits;
  public Traits Traits {
    get { return traits; }
    set { traits = value; }
  }
}

public class Traits : ObservableCollection<Trait> {}

public class Trait {
  string description;
  public string Description {
    get { return description; }
    set { description = value; }
  }
}

現在,不由僅家庭有了家庭名和成員——帶有姓名和年齡的人,而每一個人 都有一組特性,每一個都有其獨自的描述。張開我們的xaml一小塊,包括了這些 特性,如示例4-52所示。

示例4-52

<local:Families x:Key="Families">
  <local:Family FamilyName="Stooge">
    <local:Family.Members>
      <local:People>
        <local:Person Name="Larry" Age="21">
          <local:Person.Traits>
            <local:Traits>
              <local:Trait Description="In Charge" />
              <local:Trait Description="Mean" />
              <local:Trait Description="Ugly" />
            </local:Traits>
          </local:Person.Traits>
        </local:Person>
        <local:Person Name="Moe" Age="22" ></local:Person>

      </local:People>
    </local:Famil.Members>

  </local:Family>

</local:Families>

我們可以綁定第3級從頁面,如示例4-53所示。

示例4-53

<Grid DataContext="{StaticResource Families}">

  <!-- Families Column -->

  <!-- Members Column -- >

  <!-- Traits Column -->
  <StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal">
    <TextBlock TextContent="{Binding Path=Members/Name}" />
    <TextBlock TextContent=" Traits:" />
  </StackPanel>
  <ListBox Grid.Row="1" Grid.Column="2"
    IsSynchronizedWithCurrentItem="True"
    ItemsSource="{Binding Path=Members/Traits}" >
    <ListBox.ItemTemplate>
      <DataTemplate>
        <TextBlock TextContent="{Binding Path=Description}" />
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</Grid>

在Families的列標題中,回想我們沒有任何綁定;這個文本是硬編碼的:

<TextBlock …>Families:</ TextBlock>

在Members的列標題中,我們綁定了當先選中的Family對象FamilyName如下:

<TextBlock … TextContent=”{Binding Path=FamilyName}” />

邏輯上講,你可以認為是對如下進行了擴展:

<TextBlock … TextContent=”{Binding Path=Family.FamilyName}” />

這裡family是當前選中的Family對象。

取得這一級的更深一級,在具有特性的列標題中,我們將當前選中Family的 Members屬性綁定到當前選中Person的Name屬性,綁定如下:

<TextBlock …

TextContent=”{Binding Path=Members/Name}” />

再次,從邏輯上,你可以把它當作這樣的擴展:

<TextBlock …

TextContent=”{Binding Path=family.Members.person.Name}” />

這裡family是當前選中的Family對象,person是當前選中的Person對象。綁 定表達式“/”擔當了對象間的分隔符,每一級的對象假定為“當前選中的”。

列表框的源條目的綁定以同樣的方式工作,除非我們想要的是當前選中 Person的TRaits集合,而不是Name。我們的多級主從綁定的示例如圖4-22所示。

圖4-22

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved