星期二, 一月 09, 2007

Master-detail情形

Master-detail情形

原文出处:http://www.beacosta.com/Archive/2005_11_01_bcosta_archive.html

最简单的Master-detail情形就是,点击ItemsControl特定,使该项的细节在另一个控件中显示出来.例如,一个程序在ListBox 中显示了一个顾客名字列表,当点击了一个特定的顾客时,TextBlock就更新这个顾客的地址,电话号码和出生日期.

在这个帖子中我将使用太阳系的行星作为数据源:点击ListBox中的行星名字,使该行星的图片与信息显示在
被模板化的ContentControl上.ListBox扮演master的角色,ContentControl呈现细节.

在Window的资源段落,有一个提供行星数据的XmlDataProvider和一个CollectionViewSource,该 CollectionViewSource绑定Source属性到这个provider(要获得更多关于CollectionViewSource的信息,可以参考我前面的帖子.)这里是ListBox绑定到CollectionViewSource的markup:

    <!-- master -->
    <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" DisplayMemberPath="@Name" Padding="5" Margin="0,0,5,0"/>

我还需要一个ContentControl来显示选择项的细节.下面的markup看起来有点奇怪:我们绑定ContentControl(只能显示单项)到很多项的集合?(注意看它的绑定和ListBox的itemsSource的绑定很像).这个markup工作的很好,因为数据绑定引擎足够聪明,它能分辨出这两个目标.当绑定ItemsControl到数据集合,我们能得到整个集合, 当我们绑定ContentControl到数据集合,我们得到的是集合的当前项.这就是在wpf中实现Marster-detail如此简单的缘故了.

    <!-- detail -->
    <ContentControl ContentTemplate="{StaticResource detailTemplate}" Content="{Binding Source={StaticResource cvs}}"/>

为了详细说明如何在ContentControl中显示行星的细节数据,我们使用了DataTemplate.下面的markup显示了 DataTemplate的数据绑定部分.注意,因为我们是绑定到XML,因此绑定使用XPath而不是Path.

    <DataTemplate x:Key="detailTemplate">
        (...)
        <Image Source="{Binding XPath=Image, Converter={StaticResource stringToImageSource}}" />
        (...)
        <StackPanel Orientation="Horizontal" Margin="5,5,5,0">
            <TextBlock Text="Orbit: " FontWeight="Bold" />
            <TextBlock Text="{Binding XPath=Orbit}" />
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="5,0,5,0">
            <TextBlock Text="Diameter: " FontWeight="Bold"/>
            <TextBlock Text="{Binding XPath=Diameter}" />
        </StackPanel>
        <StackPanel Orientation="Horizontal" Margin="5,0,5,5">
            <TextBlock Text="Mass: " FontWeight="Bold"/>
            <TextBlock Text="{Binding XPath=Mass}" />
        </StackPanel>
        (...)
    </DataTemplate>

这里就是该示例的截图:


星期五, 一月 05, 2007

如何同步两个绑定数据的ListBox的选择项?

如何同步两个绑定数据的ListBox的选择项?


原文出处:http://www.beacosta.com/Archive/2005_11_01_bcosta_archive.html 我将会向你展示两种方法来同步绑定数据的ListBox的选择项。

在第一种解决方案中,我将会创建数据集合的定制view,然后把两个ListBox都绑定到它上面。view能够跟踪它背后数据集合的当前项,允许我们排序,组合,过滤它的数据项。CollectionViewSource是九月CTP发布的一个新的类,能够用标识来创建一个定制的view。因为在这个例子中,创建的定制的view所跟踪数据集合的当前项,currency,选择项都是同步的,因此绑定两个ListBox到相同的view能够让他们的选择项同步。

    <Window.Resources>
        <local:GreekGods x:Key="source" />
        <CollectionViewSource Source="{StaticResource source}" x:Key="cvs"/>
    </Window.Resources>



    <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" DisplayMemberPath="Name"/>
    <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" DisplayMemberPath="Name"/>

我将会在以后的帖子中介绍如何使用CollectionViewSource来排序,分组,和过滤数据项。

另一个方法也能达到同样的效果,就是设置ItemsSource属性为数据源,同时设置IsSynchronizedWithCurrentItem属性为true:

    <ListBox ItemsSource="{StaticResource source}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"/>
    <ListBox ItemsSource="{StaticResource source}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"/>

这个markup有此功能是因为当绑定到一个集合时总是会创建一个view,如果你没有指定一个view,系统就会创建一个默认的view。虽然这个 view和定制的view用同样的方式跟踪数据,但如果你有默认的view,currency和选择项是默认不同步的。改变这个默认的行为的方法就是设置 IsSynchroizedWithCurrentItem属性为true

这些数据组通过定制的回馈来区分定制views和默认views之间的默认同步方式的不同之处。这种方法能让玩家了解到view的概念,且能够根据计自己的需要精确的指定哪些能够同步,哪些不能。

下面的图片中,第一和第二个ListBox是绑定到CollectionViewSource,第三第四个设置 InSynchronizedWithCurrentItem为true.