【WPF学习】第二十一章 特殊容器

  内容控件不仅包括基本控件,如标签、按钮以及工具提示;它们还包含特殊容器,这些容器可用于构造用户界面中比较大的部分区域。

  首先介绍ScrollViewer控件,该控件直接继承自ContentControl类,提供了虚拟界面,允许用户围绕更大的元素滚动。与所有内容控件一样,ScrollViewer只能包含单个元素,虽然如此,你仍可在内部放置布局容器来保存自己需要的任意类型的元素。

  此后将分析附加继承层中的另外三个控件:GroupBox、TabItem以及Expander。所有这些控件都继承自HeaderedContentControl类,HeaderedContentControl又继承自ContentControl类。HeaderedContentControl类的作用十分简单,它表示包含单一元素内容(存储在Content属性中)和单一元素标题(存储在Header属性中)的容器。正是由于添加了标题,才使HeaderedContentControl与前面章节介绍的内容控件区别开来。重申一次,可使用标题和或内容的布局容器,将内容封装在HeaderedContentControl中。

一、ScrollViewer

  如果希望让大量内容适应有限的空间,滚动是重要特性之一。在WPF中为了获得滚动支持,需要在ScrollViewer控件中封装希望滚动的内容。

  尽管ScrollViewer控件可以包含任何内容,但通常用来封装布局容器。如下示例中,使用Grid元素创建三列,用于显示文本、文本框和按钮。为使这个Grid面板能够滚动,只需将Grid面板封装到ScrollViewer控件中,如下面的标记所示:

 <ScrollViewer Name="scroller">

            <Grid Margin="0,10,0,0" Focusable="False">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto">ColumnDefinition>
                    <ColumnDefinition Width="*" MinWidth="50" MaxWidth="800">ColumnDefinition>
                    <ColumnDefinition Width="Auto">ColumnDefinition>
                Grid.ColumnDefinitions>

                <Label Grid.Row="0" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Home:Label>
                <TextBox Grid.Row="0" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="0" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="1" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Network:Label>
                <TextBox Grid.Row="1" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="1" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="2" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Web:Label>
                <TextBox Grid.Row="2" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="2" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="3" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Secondary:Label>
                <TextBox Grid.Row="3" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="3" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="4" Grid.Column="0" Margin="3"
       VerticalAlignment="Center">Home:Label>
                <TextBox Grid.Row="4" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="4" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="5" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Network:Label>
                <TextBox Grid.Row="5" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="5" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="6" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Web:Label>
                <TextBox Grid.Row="6" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="6" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="7" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Secondary:Label>
                <TextBox Grid.Row="7" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="7" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

            Grid>

        ScrollViewer>
ScrollViewer

  最终效果如下图所示:

【WPF学习】第二十一章 特殊容器_第1张图片

 

 

   在该例中,如果改变窗口的尺寸以使窗口足以容纳所有内容,将会禁用滚动条。但仍会显示滚动条,可通过设置VerticalScrollBarVisibility属性来控制这一行为,该属性使用ScrollBarVisibility枚举值。默认值 Visible确保总是提供垂直滚动条。如果希望当需要时显示滚动条而当不需要时不显示,可将该属性设置为Auto。如果根本就不希望显示滚动条,可将该属性设置为Disable。

  ScrollViewer控件也支持水平滚动功能。但默认情况下,HorizontalScrollBarVisibility属性设置为Hidden。为了使用水平滚动功能,需要将该属性改为Visible或Auto。

  1、通过代码进行滚动

  为滚动上图中显示的窗口,可使用鼠标单击滚动条,将鼠标移到网络上并使用鼠标滚轮进行滚动,可使用Tab键查看控件,或单击网格控件的空白处并使用向上或向下的方向键进行滚动。如果这些还不够灵活,还可使用ScrollViewer类提供的方法,通过代码来滚动内容:

  •   最明显的方法是LineUp()和LineDown(),这两个方法向上和向下移动的效果相当于单击一次垂直滚动条两端的箭头按钮。
  •   还可使用PageUp()和PageDown()方法,这两个方法向上或向下滚动一整屏,相当于在滚动滑块的上面或下面单击滚动条
  •   用于水平滚动的类似方法包括LineLeft()、LineRight()、PageLeft()和PageRight()
  •   最后,还可使用ScrollToXxx()这一类方法,从而滚动到任何特定位置。对于垂直滚动,包括ScrollToEnd()和ScrollToHome(),这两个方法可以滚动到内容的顶部和底部。还有ScrollToVerticalOffset(),该方法可滚动到特定位置。对于水平滚动也有类似的方法,包括ScrollToLeftEnd()、ScrollToRightEnd()和ScrollToHorizontalOffset()。

  现在创建一个简单的示例,代码如下所示:

<Window x:Class="Controls.ScrollableTextBoxColumn"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ScrollableTextBoxColumn" Height="230.075" Width="300">
    <DockPanel>
        <Border DockPanel.Dock="Top"  BorderBrush="SteelBlue" BorderThickness="2">
            <StackPanel Margin="5" Orientation="Horizontal">
                <Button Padding="3" Click="LineUp">Line UpButton>
                <Button Padding="3" Click="LineDown">Line DownButton>
                <Button Padding="3" Click="PageUp">Page UpButton>
                <Button Padding="3" Click="PageDown">Page DownButton>
            StackPanel>
        Border>
        <ScrollViewer Name="scroller">

            <Grid Margin="0,10,0,0" Focusable="False">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                    <RowDefinition Height="Auto">RowDefinition>
                Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto">ColumnDefinition>
                    <ColumnDefinition Width="*" MinWidth="50" MaxWidth="800">ColumnDefinition>
                    <ColumnDefinition Width="Auto">ColumnDefinition>
                Grid.ColumnDefinitions>

                <Label Grid.Row="0" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Home:Label>
                <TextBox Grid.Row="0" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="0" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="1" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Network:Label>
                <TextBox Grid.Row="1" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="1" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="2" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Web:Label>
                <TextBox Grid.Row="2" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="2" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="3" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Secondary:Label>
                <TextBox Grid.Row="3" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="3" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="4" Grid.Column="0" Margin="3"
       VerticalAlignment="Center">Home:Label>
                <TextBox Grid.Row="4" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="4" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="5" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Network:Label>
                <TextBox Grid.Row="5" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="5" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="6" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Web:Label>
                <TextBox Grid.Row="6" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="6" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

                <Label Grid.Row="7" Grid.Column="0" Margin="3"
             VerticalAlignment="Center">Secondary:Label>
                <TextBox Grid.Row="7" Grid.Column="1" Margin="3"
             Height="Auto"  VerticalAlignment="Center">TextBox>
                <Button Grid.Row="7" Grid.Column="2" Margin="3" Padding="2">BrowseButton>

            Grid>

        ScrollViewer>
    DockPanel>
Window>
ScrollableTextBoxColumn.xaml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Controls
{
    /// 
    /// ScrollableTextBoxColumn.xaml 的交互逻辑
    /// 
    public partial class ScrollableTextBoxColumn : Window
    {
        public ScrollableTextBoxColumn()
        {
            InitializeComponent();
        }
        private void LineUp(object sender, RoutedEventArgs e)
        {
            scroller.LineUp();
        }
        private void LineDown(object sender, RoutedEventArgs e)
        {
            scroller.LineDown();
        }
        private void PageUp(object sender, RoutedEventArgs e)
        {
            scroller.PageUp();
        }
        private void PageDown(object sender, RoutedEventArgs e)
        {
            scroller.PageDown();
        }
    }
}
ScrollableTextBoxColumn.xaml.cs

  最终效果如下所示:

【WPF学习】第二十一章 特殊容器_第2张图片

   2、自定义滚动条

  ScrollViewer控件内置的滚动功能是很有用的。该功能允许缓慢滚动任何内容,从复杂的矢量图形乃至元素网格。不过,ScrollViewer控件最奇特的特征是允许其包含的内容参与滚动过程。下面是工作原理:

  (1)在ScrollViewer控件中放置能滚动的元素,可以是实现了IScrollInfo接口的任意元素。

  (2)通过将ScrollViewer.CanContentScroll属性设置为true,告诉ScrollViewer控件其内容知道如何进行滚动。

  (3)当和ScrollViewer控件进行交互时(通过使用滚动条、鼠标轮和滚动方法等),ScrollViewer控件通过IScrollInfo接口来调用元素的恰当方法。元素接着执行它自己的自定义滚动功能。

  IScrollInfo接口定义了一套方法,这套方法响应不同的滚动动作。例如,它包含了ScrollViewer控件提供的许多滚动方法,如LineUp()、LineDown()、PageUp()以及PageDown()。它还定义了一些处理鼠标滚轮的方法。

  实现了IScrollInfo接口的元素极少,其中一个元素是StackPanel面板容器。StackPanel类对IScrollInfo接口的实现使用逻辑滚动,从元素滚动到元素,而不是逐行滚动。

  如果在ScrollViewer控件中放置StackPanel面板,而且不设置CanContentScroll,将得到普通的滚动行为。一次可向上或向下滚动几个像素。但如果将CanContentScroll属性设置为true,那么每次单击时会滚动到下一个元素的开头:

<ScrollViewer CanContentScroll="True">
        <StackPanel>
            <Button Height="100">1Button>
            <Button Height="100">2Button>
            <Button Height="100">3Button>
            <Button Height="100">4Button>
        StackPanel>
    ScrollViewer>

  StackPanel面板的逻辑滚动系统对应用程序可能有用也可能没用。但是,如果要创建具有特殊滚动行为的自定义面板,它是必不可少的。

二、GroupBox

  GroupBox是这三个继承自HeaderedContentControl类的控件中最简单的一个。它显示为具有圆角和标题的方框。下面是一个示例,下过如下图所示:

<Window x:Class="Controls.GroupBoxDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="GroupBoxDemo" Height="300" Width="300">
    <Grid>
        <GroupBox Header="A GroupBox Test" Padding="5" Margin="5" VerticalAlignment="Top">
            <StackPanel>
                <RadioButton Margin="3">OneRadioButton>
                <RadioButton Margin="3">TwoRadioButton>
                <RadioButton Margin="3">ThreeRadioButton>
                <Button  Margin="3">SaveButton>
            StackPanel>
        GroupBox>
    Grid>
Window>
GroupBoxDemo

【WPF学习】第二十一章 特殊容器_第3张图片

 

 三、TabItem

  TabItem表示TabControl控件中的一页。TabItem类添加的唯一有意义的属性是IsSelected,该属性只是选项卡(tab)当前是否显示在TabControl控件中。下面是创建简单示例:

<Window x:Class="Controls.TabItemDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TabItemDemo" Height="300" Width="300">
    <TabControl Margin="5">
        <TabItem Header="Tab One">
            <StackPanel Margin="5">
                <CheckBox Margin="3">Setting OneCheckBox>
                <CheckBox Margin="3">Setting TwoCheckBox>
                <CheckBox Margin="3">Setting ThreeCheckBox>
            StackPanel>
        TabItem>
        <TabItem Header="Tab Two">
            <StackPanel Margin="5">
                <CheckBox Margin="3">Setted OneCheckBox>
                <CheckBox Margin="3">Setted TwoCheckBox>
                <CheckBox Margin="3">Setted ThreeCheckBox>
            StackPanel>
        TabItem>
    TabControl>
Window>
TabItemDemo.xaml

【WPF学习】第二十一章 特殊容器_第4张图片

  可以使用TabStripPlacement属性,使各个选项卡在选项卡控件的侧边显示,而不是在正常顶部位置显示。

  与Content属性意义,Header属性也可以接受任何类型的对象。继承自UIElement的类通过渲染来显示,对于内敛文本以及其他所有对象则使用ToString()方法。这意味着可以创建组合框或选项卡,在他们的标题中包含图形内容或任意元素。下面是一个示例:

<Window x:Class="Controls.GraphicalTabTitles"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="GraphicalTabTitles" Height="300" Width="300">
    <TabControl Margin="5" >
        <TabItem>
            <TabItem.Header>
                <StackPanel>
                    <TextBlock Margin="3">Image and Text Tab TitleTextBlock>
                    <Image Source="happyface.jpg" Stretch="None">Image>
                StackPanel>
            TabItem.Header>
            <StackPanel Margin="5">
                <CheckBox Margin="3">Setting OneCheckBox>
                <CheckBox Margin="3">Setting TwoCheckBox>
                <CheckBox Margin="3">Setting ThreeCheckBox>
            StackPanel>
        TabItem>
        <TabItem Header="Tab Two">
            <StackPanel Margin="5">
                <CheckBox Margin="3">Setted OneCheckBox>
                <CheckBox Margin="3">Setted TwoCheckBox>
                <CheckBox Margin="3">Setted ThreeCheckBox>
            StackPanel>
        TabItem>
    TabControl>
Window>
GraphicalTabTitles

【WPF学习】第二十一章 特殊容器_第5张图片

 

 四、Expander

   最奇特的具有标题的内容控件是Expander控件。它封装了一块内容,通过单击小箭头按钮可以显示或隐藏所包含的内容。

  使用Expander控件是十分简单的——只需在该控件内部包装希望使其能够折叠的内容。通常,每个Expander控件开始时都是折叠的,但可在标记中(或代码中)通过设置IsExpanded属性来改变这种行为。下面是一个简单Expander示例:

<Window x:Class="Controls.ExpandableContent"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpandableContent" Height="300" Width="300" SizeToContent="Height">
    <StackPanel>
        <Expander Margin="5" Padding="5"  Header="Region One"
                  BorderThickness="1" BorderBrush="Black">
            <Button Padding="3">Hidden Button OneButton>
        Expander>
        <Expander Margin="5" Padding="5" Header="Region Two" 
            BorderThickness="1" BorderBrush="Black">
            <TextBlock TextWrapping="Wrap">
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. Proin rutrum arcu vitae tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque libero dui, eleifend faucibus, auctor at, aliquet a, nulla. Nunc eros. Phasellus mauris nisi, eleifend nec, adipiscing nec, luctus nec, lacus. Aliquam justo metus, vestibulum non, accumsan id, hendrerit at, nibh. Praesent accumsan urna quis tortor. Proin erat libero, facilisis nec, rhoncus ut, malesuada ut, ipsum. Donec id nibh.
            TextBlock>
        Expander>
        <Expander Margin="5" Padding="5" Header="Region Three" IsExpanded="True"
              BorderThickness="1" BorderBrush="Black">
            <Button Padding="3">Hidden Button TwoButton>
        Expander>
    StackPanel>
Window>
ExpandableContent

【WPF学习】第二十一章 特殊容器_第6张图片

 

 

 

   还可以选择扩展器的方向。上图使用的是标准值(Down),但也可将ExpandDirection树上设置为Up、Left或Right。当折叠Expander时,箭头始终指向将要展开的方向。

  当使用不同的ExpandDirection值,情况就比较有趣了,因为对用户界面其他部分的影响取决于容器的类型。有些容器(如WrapPanel面板)只要挤压其他元素使其离开原来的位置。其他容器,如Grid面板,可以选择按比例或自动改变大小。下面有一个示例使用不同展开程度,该示例有一个具有4个单元格的网格。每个单元格中都包含一个具有不同展开方向的扩展器。例按比例改变其大小,从而强制Expander控件中的文本进行换行(自动改变尺寸的列回简单地被拉伸以适应文本,使它比窗口还大)。行被设置为自动改变尺寸,所以会扩展以容纳附加的内容。

示例代码如下所示:

<Window x:Class="Controls.MultiDirectionExpanders"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MultiDirectionExpanders" Height="327.2" Width="328.8">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto">RowDefinition>
            <RowDefinition Height="Auto">RowDefinition>
        Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition >ColumnDefinition>
            <ColumnDefinition>ColumnDefinition>
        Grid.ColumnDefinitions>
        <Expander Margin="5" Padding="5" Header="Region One"
              BorderThickness="1" BorderBrush="Black">
            <TextBlock TextWrapping="Wrap">
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
        Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien.
            TextBlock>
        Expander>
        <Expander Grid.Column="1" 
      Margin="5" Padding="5" Header="Region Two" ExpandDirection="Right"  
              BorderThickness="1" BorderBrush="Black">
            <TextBlock TextWrapping="Wrap">
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
        Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien.
            TextBlock>
        Expander>
        <Expander Grid.Row="1"
      Margin="5" Padding="5" Header="Region Three" ExpandDirection="Up"
              BorderThickness="1" BorderBrush="Black">
            <TextBlock TextWrapping="Wrap">
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
        Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien.
            TextBlock>
        Expander>
        <Expander Grid.Row="1" Grid.Column="1" 
      Margin="5" Padding="5" Header="Region Three" ExpandDirection="Left" 
              BorderThickness="1" BorderBrush="Black">
            <TextBlock TextWrapping="Wrap">
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
        Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien.
            TextBlock>
        Expander>
    Grid>
Window>
MultiDirectionExpanders

【WPF学习】第二十一章 特殊容器_第7张图片

 

 

 【WPF学习】第二十一章 特殊容器_第8张图片

 

 

 【WPF学习】第二十一章 特殊容器_第9张图片

 

 

 

   在WPF程序中使用Expander控件是非常合适的,因为WPF鼓励使用流式布局模型,从而可以很方便地处理会大幅增大或缩小的内容区域。

  如果要使其他控件与Expander同步,可处理Expanded和Collapsed事件。这些事件的名称并未表明其含义,这些事件正好在显示或隐藏内容前触发。这两个事件为实现延迟加载提供一种有用的方法。例如,如果创建Expander控件中的内容非常耗时,可能会直到要显示时才检索这些内容。或者可能希望在显示之前更新内容。无论哪种情况,都可以通过响应Expanded事件来执行相应的工作。

  通常,当展开Expander时,它会增大以适应所包含的内容。当展开所有内容后,如果窗口不足以显示所有内容,这可能会带来问题。下面是处理该问题的集中策略:

  •   为窗口设置最小尺寸(使用MinWidth和MinHeight属性),确保窗口在最小时也可以容纳所有内容。
  •   设置窗口的SizeToContent属性,从而当打开或关闭Expander控件时,是窗口自动扩展为所需的大小。通常将SizeToContent属性设置为Manual,但也可以使用Width或Height,以使窗口为了适应所包含的内容在任意方向上扩展或收缩。
  •   通过硬编码Expander控件的Height和Widht属性来限制其尺寸,但当Expander控件中的内容太长时,可能会裁剪掉部分内容。
  •   使用ScrollViewer控件创建可滚动的扩展区域。

  对于大多数情况,这些技术都是非常简单的。唯一需要进一步说明的是如何组合使用Expander控件和ScrollViewer控件,为让这个方法凑效,需要赢编码ScrollViewer控件的尺寸。否则,ScrollViewer控件会进行扩展以适应它包含的内容。下面是一个示例:

<Window x:Class="Controls.ExpandableScrollableContent"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpandableScrollableContent" Height="300" Width="300">
    <StackPanel>
        <Expander Margin="5" Padding="5" Header="Region One">
        Expander>
        <Expander Margin="5" Padding="5" Header="Region Two" >
            <ScrollViewer Height="50" >
                <TextBlock TextWrapping="Wrap">
          Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. Proin rutrum arcu vitae tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque libero dui, eleifend faucibus, auctor at, aliquet a, nulla. Nunc eros. Phasellus mauris nisi, eleifend nec, adipiscing nec, luctus nec, lacus. Aliquam justo metus, vestibulum non, accumsan id, hendrerit at, nibh. Praesent accumsan urna quis tortor. Proin erat libero, facilisis nec, rhoncus ut, malesuada ut, ipsum. Donec id nibh.
                TextBlock>
            ScrollViewer>
        Expander>
        <Expander Margin="5" Padding="5" Header="Region Three" IsExpanded="True">
            <Button Padding="3">Hidden Button TwoButton>
        Expander>
    StackPanel>
Window>
ExpandableScrollableContent

【WPF学习】第二十一章 特殊容器_第10张图片

 

   如果有一个系统,能让Expander控件根据窗口的可用空间,设置内容区域的尺寸,那将是非常好的。但这会明显增加复杂度(例如,当Expander控件展开时,如果在多个区域共享空间)。Grid布局容器看起来像是潜在的解决方案,但它不能和Expander控件很好地集成。如果尝试这样的做的话,当折叠Expander控件时,可能导致非常奇怪的行为,不能正确地更新网格的行高。

 

你可能感兴趣的:(【WPF学习】第二十一章 特殊容器)