天天看點

【WPF學習】第十章 WPF布局示例

  前幾章用了相當大的篇幅研究有關WPF布局容器的複雜内容。在掌握了這些基礎知識後,就可以研究幾個完整的布局示例。通過研究完整的布局示例,可更好的了解各種WPF布局概念在實際視窗中的工作方式。

一、列設定

  布局容器(如Grid面闆)使得視窗建立整個布局結構變得非常容易。例如,分析如下顯示的視窗及設定。該視窗在一個表格結構中排列各個元件——标簽、文本框以及按鈕。

【WPF學習】第十章 WPF布局示例

   為建立這一表格,首先定義網格的行和列。行定義足夠簡單——隻需要将每行的尺寸設定為所含内容的高度。這意味着所有行都将使用最大元素的高度,在該示例中,最大的元素是第三列中的Browse按鈕。

  接下來需要建立列。第一列和最後一列的尺寸要适合其内容(分别是标簽文本和Browse按鈕)。中間列占用所有剩餘空間,這意味着當視窗變大時,該列的尺寸會增加,這樣可有更大的空間顯示選擇的檔案夾(如果希望拉伸不超過一定的最大寬度,在定義列時可使用MaxWidth屬性,就像對單個元素使用MaxWidth屬性一樣)。

  現在已經具備了基本結構,接下來隻需要在恰當的單元格中放置元素。然而,還需要仔細考慮邊距和對其方式。每個元素需要基本的邊距(3個機關較恰當)以在其周圍添加一些空間。此外,标簽和文本框的垂直方向上需要劇中,因為他們沒有Browse按鈕高。最後,文本框需要使用自動設定尺寸模式,這樣它會被拉伸以充滿整列。

  示例完整的代碼如下所示:

<Window x:Class="LayoutDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Margin="3,3,10,3">
        <Grid.RowDefinitions>
            <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="*"></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">Browse</Button>
        <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">Browse</Button>
        <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">Browse</Button>
        <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">Browse</Button>
    </Grid>
</Window>      

  一個不是非常明顯的事實是,因為使用了Grid控件,是以該視窗時非常靈活的。沒有任何一個元素——标簽、文本框以及按鈕——時通過寫死來定位和設定尺寸的。是以,可通過簡單地修改ColumnDefinition元素來快速改變整個網絡。甚至,如果添加了包含更長标簽文本的行(迫使第一列更寬),就會調整整個網格使其保持一緻,包括已經添加的行。如果希望在兩行之間添加元素——例如,添加分割線以區分視窗的不同部分——可保持網格的列定義不變,但使用ColumnSpan屬性拉伸某個元素,使其覆寫更大的區域。

二、動态内容

  與上面的示範的列設定一樣,當修訂應用程式時,可友善地修改使用WPF布局容器的視窗并且可以很容易地時視窗适應對應用程式的修訂。這樣的靈活性不僅能使開發人員在設計時受益,而且如果需要顯示在運作時變化很大的内容,這樣是非常有用的。

  一個例子是本地化文本——對于不同的區域,在使用者界面中顯示的文本需要翻譯成不同的語言。在老式的基于坐标的應用程式中,改變視窗中的文本會造成混亂,部分原因是少了英國文本翻譯成許多語言後會變得特别大。盡管允許改變元素的尺寸以适應更大的文本,但這樣做警察會使整體視窗失去平衡。

  下圖示範WPF布局控件時如何聰明地解決這一問題。在這個示例中,使用者界面可選擇短文本和長文本。當使用長文本時,包含文本的按鈕會自動改變其尺寸,而對其他内容也會相應的調整位置。并且是以改變了尺寸的按鈕共享同一布局容器(在該例中是一個表格列),是以整個使用者界面都會改變尺寸。最終結果是所有按鈕保持一緻的尺寸——最大按鈕的尺寸。

              

【WPF學習】第十章 WPF布局示例
【WPF學習】第十章 WPF布局示例

  為實作這個效果,視窗使用一個具有兩行兩列的表格進行分割。左邊的列包含可改變大小的按鈕,而右邊的列包含文本框。底行用于放置Close按鈕,底行和頂行位于同一個表格中,進而可以根據頂行改變尺寸。

  示例完整代碼如下所示:

<Window x:Class="LayoutDemo.LayoutWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="LayoutWindow" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Row="0" Grid.Column="0">
            <Button Name="btnPrev" Margin="10,10,10,3">Prev</Button>
            <Button Name="btnNext" Margin="10,3,10,3">Next</Button>
            <CheckBox Name="chkLongText" Margin="10,10,10,10"  Checked="chkLongText_Checked" Unchecked="chkLongText_UnChecked">Show Long Text</CheckBox>
        </StackPanel>
        <TextBox Grid.Row="0" Grid.Column="1" Margin="0,10,10,10" TextWrapping="Wrap" Grid.RowSpan="2">
            This is a test that demonstrates how buttons adapt themselfes to fit the content they contain when they aren't explicitly sized.This behavior makes localization much easier.
        </TextBox>
        <Button Grid.Row="1" Grid.Column="0" Name="btnClose" Margin="10,3,10,10">
            Close
        </Button>
    </Grid>
</Window>      

  背景代碼如下所示:

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 LayoutDemo
{
    /// <summary>
    /// LayoutWindow.xaml 的互動邏輯
    /// </summary>
    public partial class LayoutWindow : Window
    {
        public LayoutWindow()
        {
            InitializeComponent();
        }

        

        private void chkLongText_Checked(object sender, RoutedEventArgs e)
        {
            this.btnPrev.Content = "<-Go to the Previous Window";
            this.btnNext.Content = "Go to the Next Window ->";
        }

        private void chkLongText_UnChecked(object sender, RoutedEventArgs e)
        {
            this.btnPrev.Content = "Prev";
            this.btnNext.Content = "Next";
        }
    }
}      

  Visiblity屬性是UIEelement基類的一部分,是以放置于WPF視窗中的任何内容都支援該屬性。該屬性可使用三個值,它們來自System.Windows.Visiblity枚舉,如下表所示:

【WPF學習】第十章 WPF布局示例

作者:Peter Luo

出處:https://www.cnblogs.com/Peter-Luo/

本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,并保留此段聲明,否則保留追究法律責任的權利。

繼續閱讀