WPF中的主从(Master-Detail)实现

    下面这个例子本身来自微软官网,由于没有找到官网源码,我在这里自己实现了一下。还是向官网致敬。

    什么是Master-Detail?直接上个图给大家看,就知道了:


    这看起来真复杂,点中ListBox里出现的人名,下面要出现这个人的具体信息:姓、名、籍贯。这种应用场景还真不少。如果能够掌握岂不是爽,客官不急,下面听我慢慢道来。

    类似像上面这样子在某个列表中选中一项信息概要,旁边某处就能够显示选中元素相应的详细信息的,微软就称之为Master-Detail应用。

    好了,像上面这个例子怎么实现呢?我们一步一步来,首先我们想到的肯定是要实现一个Person类,这个类包含姓、名、籍贯。这个类的代码相信大部分人都会写,如下所示:

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string HomeTown { get; set; }
        public Person(string f, string l,string h)
        {
            FirstName = f;
            LastName = l;
            HomeTown = h;
        }

        public override string ToString()
        {
            return FirstName;
        }
    }

    看,这个类里面看不到一丁点与界面交互的意思,全是赤裸裸的纯C#代码。不过,这里隐隐的有个ToString()需要稍微解释下:

    Person类实现了ToString()方法,这样子ListBox绑定包含Person的集合后,不显示设置DisplayMemberPath,那么就会默认调用Person的ToString()来显示每个项的内容到ListBox控件当中。

    下面是定义People类,这个类是Person的集合:

    public class People : ObservableCollection<Person>
    {
        public People()
        {
            Add(new Person("Yun", "Ma", "HangZhou"));
            Add(new Person("Qiangdong", "Liu", "NanJing"));
            Add(new Person("Yanhong", "Li", "BeiJing"));
        }
    }

    很清晰,上面代码所示,添加了三个人的信息。注意没有一丁点和界面交互的意思。

    上面的两段代码添加到你的MainWindows类所在的c#源文件当中。

扫描二维码关注公众号,回复: 569140 查看本文章

    XMAL中的代码如下所示:

    <Window.Resources>
        <local:People x:Key="MyFriends"/>
        <DataTemplate x:Key="DetailTemplate">
            <Border Width="300" Height="100" Margin="20"
          BorderBrush="Aqua" BorderThickness="1" Padding="8">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Row="0" Grid.Column="0" Text="First Name:"/>
                    <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=FirstName}"/>
                    <TextBlock Grid.Row="1" Grid.Column="0" Text="Last Name:"/>
                    <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=LastName}"/>
                    <TextBlock Grid.Row="2" Grid.Column="0" Text="Home Town:"/>
                    <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=HomeTown}"/>
                </Grid>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <StackPanel>
        <TextBlock FontFamily="Verdana" FontSize="11" Margin="5,15,0,10" FontWeight="Bold">My Friends:</TextBlock>
        <ListBox Width="200" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource MyFriends}}"/>
        <TextBlock FontFamily="Verdana" FontSize="11" Margin="5,15,0,5" FontWeight="Bold">Information:</TextBlock>
        <ContentControl Content="{Binding Source={StaticResource MyFriends}}" ContentTemplate="{StaticResource DetailTemplate}"/>
    </StackPanel>

    如上所示,软件界面的ListBox和ContentControl两个最主要的控件都绑定到了MyFriends这个key所代表的资源当中。ListBox的绑定如下:

ItemsSource="{Binding Source={StaticResource MyFriends}}"

    这个很好理解,表示绑定到了Person集合People中,这样子ListBox的每个项就会显示集合中的每个内容,因为ListBox中省却了DisplayMemberPath属性的设置,所以显示的具体内容是由集合中的每个项(也就是Person)的ToString()方法的返回值来决定的。

    ContentControl控件的绑定如下所示:

Content="{Binding Source={StaticResource MyFriends}}"

    可能觉得比较奇怪,为什么明明是内容(Content)控件,为何要绑定到一个集合当中呢?这里解释给大家,WPF在这个地方比较智能,它内部框架默认是绑定到这个绑定集合所指向的当前项(CurrentItem)。

    那好了,新的问题来了,ListBox当中选中集合中的某一项,怎么让ContentCotrol控件中显示相应选中项的详细信息呢? 大家可能想到的一种办法是自己在C#后台写一堆操作代码:ListBox选中事件SelectionChanged中添加相应的事件来改变ContentControl控件的具体内容。这是一个思路,不过要指出的是WPF其实在这点上已经帮我们前期做好了框架工作了。你只要在XMAL文件的ListBox控件当中添加

IsSynchronizedWithCurrentItem="True" 

    一切就搞定了,你不需要再额外添加代码,WPF就是这么任性,你在后台几乎都没有加任何和界面操作相关的哪怕一句代码,神奇所在,界面与逻辑完全隔离!!!跟界面相关的交互代码几乎全部在XMAL中搞定。

    好,那么我们就介绍下IsSynchronizeWithCurrentItem是怎么工作的?那你可就可以参考我的另外一篇博文:

点击打开链接


猜你喜欢

转载自blog.csdn.net/qq_16587307/article/details/79592057