1. 程式人生 > 其它 >【WPF】 Canvas介紹

【WPF】 Canvas介紹

      

從這篇文章開始是對WPF中的介面如何佈局做一個較簡單的介紹,大家都知道:UI是做好一個軟體很重要的因素,如果沒有一個漂亮的UI,功能做的再好也無法吸引很多使用者使用,而且沒有漂亮的介面,那麼普通使用者會感覺這個軟體沒有多少使用價值。

1、canvas 中的元素通過canvas的附件屬性left|right、bottom|top 來佈局, 不能同時使用left 和right或者top和bottom

2、zindex控制層級。

一. 總體介紹

        WPF的佈局控制元件都在System.Windows.Controls.Panel這個基類下面,使用 WPF提供的各種控制元件在WPF應用程式中介面進行佈局,同時對各種子控制元件(如按鈕、文字框,下拉框等)進行排列組合。

Pane類的公共屬性太多了。就簡單介紹幾個常見的屬性如下表。

  

名稱

說明

Cursor

獲取或設定在滑鼠指標位於此元素上時顯示的游標。 

DataContext

獲取或設定元素參與資料繫結時的資料上下文。 

Dispatcher

獲取與此 DispatcherObject 關聯的 Dispatcher。 

FontFamily

獲取或設定控制元件的字體系列。 

FontSize

獲取或設定字號。 

FontWeight

獲取或設定指定的字型的權重或粗細。 

Foreground

獲取或設定描述前景色的畫筆。 

HandlesScrolling

獲取一個值控制元件是否支援滾動。

Height

獲取或設定元素的建議高度。 

HorizontalContentAlignment

獲取或設定控制元件內容的水平對齊。 

IsLoaded

獲取一個值,該值指示是否已載入此元素以供呈現。 

IsMouseOver

獲取一個值,該值指示滑鼠指標是否位於此元素(包括可視樹上的子元素)上。這是一個依賴項屬性。 

IsTabStop

獲取或設定一個值控制是否在選項卡上導航包含。 

IsVisible

獲取一個值,該值指示此元素在使用者介面 (UI) 中是否可見。這是一個依賴項屬性。 

LayoutTransform

獲取或設定在執行佈局時應該應用於此元素的圖形轉換方式。 

Margin

獲取或設定元素的外邊距。 

Name

獲取或設定元素的標識名稱。 該名稱提供一個引用,以便當 XAML 處理器在處理過程中構造標記元素之後,程式碼隱藏(如事件處理程式程式碼)可以對該元素進行引用。

Opacity

獲取或設定當 UIElement 在使用者介面 (UI) 中呈現時為其整體應用的不透明度因子。這是一個依賴項屬性。 

Padding

獲取或設定控制元件中的空白。 

RenderTransform

獲取或設定影響此元素的呈現位置的轉換資訊。這是一個依賴項屬性。 

TabIndex

獲取或設定使用 tab 鍵時,確定順序接收焦點的元素的值,當用戶將控制元件定位。 

Tag

獲取或設定任意物件值,該值可用於儲存關於此元素的自定義資訊。 

ToolTip

獲取或設定在使用者介面 (UI) 中為此元素顯示的工具提示物件。 

TouchesCaptured

獲取在此元素上捕獲的所有觸控裝置。 

TouchesCapturedWithin

獲取在此元素或其視覺化樹中的任何子元素上捕獲的所有觸控裝置。 

VerticalContentAlignment

獲取或設定控制元件內容的垂直對齊方式。 

Visibility

獲取或設定此元素的使用者介面 (UI) 可見性。這是一個依賴項屬性。 

VisualOpacityMask

獲取或設定 Brush 值,該值表示 Visual 的不透明蒙板。 

Width

獲取或設定元素的寬度。 

       一個Panel 的呈現就是測量和排列子控制元件,然後在螢幕上繪製它們。所以在佈局的過程中會經過一系列的計算,那麼子控制元件越多,執行的計算次數就越多,則效能就會變差。如果不需要進行復雜的佈局,則儘量少用複雜佈局控制元件(如 Grid和自定義複雜的Panel);如果能簡單佈局實現就儘量使用構造相對簡單的佈局(如 Canvas、UniformGrid等),這種佈局可帶來更好的效能。 如果有可能,我們應儘量避免呼叫 UpdateLayout方法。 
      每當Panel內的子控制元件改變其位置時,佈局系統就可能觸發一個新的處理過程。對此,瞭解哪些事件會呼叫佈局系統就很重要,因為不必要的呼叫可能導致應用程式效能變差。 
       換句話說,佈局是一個遞迴系統,實現在螢幕上對控制元件進行大小調整、定位和繪製,然後進行呈現。具體如下圖,要實現控制元件0的佈局,那麼先要實現0的子控制元件 01,02...的佈局,要實現01的佈局,那麼得實現01的子控制元件001,002...的佈局,如此迴圈直到子控制元件的佈局完成後,再完成父控制元件的佈局, 最後遞歸回去直到遞迴結束,這樣整個佈局過程就完成了.

      佈局系統為Panel中的每個子控制元件完成兩個處理過程:測量處理過程(Measure)和排列處理過程(Arrange)。每個子 Panel 均提供自己的 MeasureOverride 和 ArrangeOverride 方法,以實現自己特定的佈局行為。

二. Canvas 

      Canvas是最基本的面板,只是一個儲存控制元件的容器,它不會自動調整內部元素的排列及大小,它僅支援用顯式座標定位控制元件,它也允許指定相對任何角的座標,而不僅僅是左上角。可以使用Left、Top、Right、 Bottom附加屬性在Canvas中定位控制元件。通過設定Left和Right屬性的值表示元素最靠近的那條邊,應該與Canvas左邊緣或右邊緣保持一個固定的距離,設定Top和Bottom的值也是類似的意思。實質上,你在選擇每個控制元件停靠的角時,附加屬性的值是作為外邊距使用的。如果一個控制元件沒有使 用任何附加屬性,它會被放在Canvas的左上方(等同於設定Left和Top為0)。

      Canvas的主要用途是用來畫圖。Canvas預設不會自動裁減超過自身範圍的內容,即溢位的內容會顯示在Canvas外面,這是因為預設 ClipToBounds=”False”;我們可以通過設定ClipToBounds=”True”來裁剪多出的內容。

 如果將ClipToBounds屬性設為true,在設計介面將會對子元素的超出部分進行裁剪:

接下來我們來看兩個例項,第一個例項使用XAML程式碼實現:

<Window x:Class="WpfApp1.WindowCanvas"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="WindowCanvas" Height="400" Width="500">

    <Grid>

        <Canvas Margin="0,0,0,0" Background="White">

            <Rectangle Fill="Blue" 

                Stroke="Azure" 

                Width="250" 

                Height="200" 

                Canvas.Left="210" Canvas.Top="101"/>

            <Ellipse Fill="Red" 

                Stroke="Green" 

                Width="250" Height="100" 

                Panel.ZIndex="1" 

                Canvas.Left="65" Canvas.Top="45"/>

        </Canvas>

        <Canvas>

            <Button Name="btnByCode" Click="btnByCode_Click">後臺程式碼實現</Button>

        </Canvas>

    </Grid>

</Window>

 

例項後的效果如下圖。

第二個例項,我們使用後臺程式碼來實現。下面紅色字型是如何設定控制元件的Canvas.Left 和Canvas.Top值

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

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 WpfApp1

{

    /// <summary>

    /// WindowCanvas.xaml 的互動邏輯

    /// </summary>

    public partial class WindowCanvas : Window

    {

        public WindowCanvas()

        {

            InitializeComponent();

            

        }

 

        public void DisplayCanvas()

        {

            Canvas canv = new Canvas();

            //把canv新增為窗體的子控制元件

            this.Content = canv;

            canv.Margin = new Thickness(0, 0, 0, 0);

            canv.Background = new SolidColorBrush(Colors.White);

 

            //Rectangle

            Rectangle r = new Rectangle();

            r.Fill = new SolidColorBrush(Colors.Red);

            r.Stroke = new SolidColorBrush(Colors.Red);

            r.Width = 200;

            r.Height = 140;

            r.SetValue(Canvas.LeftProperty, (double)200);

            r.SetValue(Canvas.TopProperty, (double)120);

            canv.Children.Add(r);

            //Ellipse

            Ellipse el = new Ellipse();

            el.Fill = new SolidColorBrush(Colors.Blue);

            el.Stroke = new SolidColorBrush(Colors.Blue);

            el.Width = 240;

            el.Height = 80;

            el.SetValue(Canvas.ZIndexProperty, 1);

            el.SetValue(Canvas.LeftProperty, (double)100);

            el.SetValue(Canvas.TopProperty, (double)80);

            canv.Children.Add(el);

 

        }

 

        private void btnByCode_Click(object sender, RoutedEventArgs e)

        {

            DisplayCanvas();

        }

    }

}

 

 實現後的效果如下圖。

最後 要說明一點Canvas內的子控制元件不能使用兩個以上的Canvas附加屬性,如果同時設定Canvas.Left和Canvas.Right屬性,那麼後者將會被忽略。

2、ZIndex屬性

Canvas面板中可能會有多個相互重疊的元素,可以設定Canvas的ZIndex附加屬性,來控制他們的重疊方式 ZIndex屬性預設值都是0,屬性值必須是整數。

除此之外,我們還可以通過程式碼的方式設定ZIndex的值,程式碼如下:Canvas.SetZIndex(this.btn, 2);

3、測量處理過程(Measure)和排列處理過程(Arrange)

      

從這篇文章開始是對WPF中的介面如何佈局做一個較簡單的介紹,大家都知道:UI是做好一個軟體很重要的因素,如果沒有一個漂亮的UI,功能做的再好也無法吸引很多使用者使用,而且沒有漂亮的介面,那麼普通使用者會感覺這個軟體沒有多少使用價值。

1、canvas 中的元素通過canvas的附件屬性left|right、bottom|top 來佈局, 不能同時使用left 和right或者top和bottom

2、zindex控制層級。

一. 總體介紹

        WPF的佈局控制元件都在System.Windows.Controls.Panel這個基類下面,使用 WPF提供的各種控制元件在WPF應用程式中介面進行佈局,同時對各種子控制元件(如按鈕、文字框,下拉框等)進行排列組合。

Pane類的公共屬性太多了。就簡單介紹幾個常見的屬性如下表。

  

名稱

說明

Cursor

獲取或設定在滑鼠指標位於此元素上時顯示的游標。 

DataContext

獲取或設定元素參與資料繫結時的資料上下文。 

Dispatcher

獲取與此 DispatcherObject 關聯的 Dispatcher。 

FontFamily

獲取或設定控制元件的字體系列。 

FontSize

獲取或設定字號。 

FontWeight

獲取或設定指定的字型的權重或粗細。 

Foreground

獲取或設定描述前景色的畫筆。 

HandlesScrolling

獲取一個值控制元件是否支援滾動。

Height

獲取或設定元素的建議高度。 

HorizontalContentAlignment

獲取或設定控制元件內容的水平對齊。 

IsLoaded

獲取一個值,該值指示是否已載入此元素以供呈現。 

IsMouseOver

獲取一個值,該值指示滑鼠指標是否位於此元素(包括可視樹上的子元素)上。這是一個依賴項屬性。 

IsTabStop

獲取或設定一個值控制是否在選項卡上導航包含。 

IsVisible

獲取一個值,該值指示此元素在使用者介面 (UI) 中是否可見。這是一個依賴項屬性。 

LayoutTransform

獲取或設定在執行佈局時應該應用於此元素的圖形轉換方式。 

Margin

獲取或設定元素的外邊距。 

Name

獲取或設定元素的標識名稱。 該名稱提供一個引用,以便當 XAML 處理器在處理過程中構造標記元素之後,程式碼隱藏(如事件處理程式程式碼)可以對該元素進行引用。

Opacity

獲取或設定當 UIElement 在使用者介面 (UI) 中呈現時為其整體應用的不透明度因子。這是一個依賴項屬性。 

Padding

獲取或設定控制元件中的空白。 

RenderTransform

獲取或設定影響此元素的呈現位置的轉換資訊。這是一個依賴項屬性。 

TabIndex

獲取或設定使用 tab 鍵時,確定順序接收焦點的元素的值,當用戶將控制元件定位。 

Tag

獲取或設定任意物件值,該值可用於儲存關於此元素的自定義資訊。 

ToolTip

獲取或設定在使用者介面 (UI) 中為此元素顯示的工具提示物件。 

TouchesCaptured

獲取在此元素上捕獲的所有觸控裝置。 

TouchesCapturedWithin

獲取在此元素或其視覺化樹中的任何子元素上捕獲的所有觸控裝置。 

VerticalContentAlignment

獲取或設定控制元件內容的垂直對齊方式。 

Visibility

獲取或設定此元素的使用者介面 (UI) 可見性。這是一個依賴項屬性。 

VisualOpacityMask

獲取或設定 Brush 值,該值表示 Visual 的不透明蒙板。 

Width

獲取或設定元素的寬度。 

       一個Panel 的呈現就是測量和排列子控制元件,然後在螢幕上繪製它們。所以在佈局的過程中會經過一系列的計算,那麼子控制元件越多,執行的計算次數就越多,則效能就會變差。如果不需要進行復雜的佈局,則儘量少用複雜佈局控制元件(如 Grid和自定義複雜的Panel);如果能簡單佈局實現就儘量使用構造相對簡單的佈局(如 Canvas、UniformGrid等),這種佈局可帶來更好的效能。 如果有可能,我們應儘量避免呼叫 UpdateLayout方法。 
      每當Panel內的子控制元件改變其位置時,佈局系統就可能觸發一個新的處理過程。對此,瞭解哪些事件會呼叫佈局系統就很重要,因為不必要的呼叫可能導致應用程式效能變差。 
       換句話說,佈局是一個遞迴系統,實現在螢幕上對控制元件進行大小調整、定位和繪製,然後進行呈現。具體如下圖,要實現控制元件0的佈局,那麼先要實現0的子控制元件 01,02...的佈局,要實現01的佈局,那麼得實現01的子控制元件001,002...的佈局,如此迴圈直到子控制元件的佈局完成後,再完成父控制元件的佈局, 最後遞歸回去直到遞迴結束,這樣整個佈局過程就完成了.

      佈局系統為Panel中的每個子控制元件完成兩個處理過程:測量處理過程(Measure)和排列處理過程(Arrange)。每個子 Panel 均提供自己的 MeasureOverride 和 ArrangeOverride 方法,以實現自己特定的佈局行為。

二. Canvas 

      Canvas是最基本的面板,只是一個儲存控制元件的容器,它不會自動調整內部元素的排列及大小,它僅支援用顯式座標定位控制元件,它也允許指定相對任何角的座標,而不僅僅是左上角。可以使用Left、Top、Right、 Bottom附加屬性在Canvas中定位控制元件。通過設定Left和Right屬性的值表示元素最靠近的那條邊,應該與Canvas左邊緣或右邊緣保持一個固定的距離,設定Top和Bottom的值也是類似的意思。實質上,你在選擇每個控制元件停靠的角時,附加屬性的值是作為外邊距使用的。如果一個控制元件沒有使 用任何附加屬性,它會被放在Canvas的左上方(等同於設定Left和Top為0)。

      Canvas的主要用途是用來畫圖。Canvas預設不會自動裁減超過自身範圍的內容,即溢位的內容會顯示在Canvas外面,這是因為預設 ClipToBounds=”False”;我們可以通過設定ClipToBounds=”True”來裁剪多出的內容。

 如果將ClipToBounds屬性設為true,在設計介面將會對子元素的超出部分進行裁剪:

接下來我們來看兩個例項,第一個例項使用XAML程式碼實現:

<Window x:Class="WpfApp1.WindowCanvas"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="WindowCanvas" Height="400" Width="500">

    <Grid>

        <Canvas Margin="0,0,0,0" Background="White">

            <Rectangle Fill="Blue" 

                Stroke="Azure" 

                Width="250" 

                Height="200" 

                Canvas.Left="210" Canvas.Top="101"/>

            <Ellipse Fill="Red" 

                Stroke="Green" 

                Width="250" Height="100" 

                Panel.ZIndex="1" 

                Canvas.Left="65" Canvas.Top="45"/>

        </Canvas>

        <Canvas>

            <Button Name="btnByCode" Click="btnByCode_Click">後臺程式碼實現</Button>

        </Canvas>

    </Grid>

</Window>

 

例項後的效果如下圖。

第二個例項,我們使用後臺程式碼來實現。下面紅色字型是如何設定控制元件的Canvas.Left 和Canvas.Top值

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

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 WpfApp1

{

    /// <summary>

    /// WindowCanvas.xaml 的互動邏輯

    /// </summary>

    public partial class WindowCanvas : Window

    {

        public WindowCanvas()

        {

            InitializeComponent();

            

        }

 

        public void DisplayCanvas()

        {

            Canvas canv = new Canvas();

            //把canv新增為窗體的子控制元件

            this.Content = canv;

            canv.Margin = new Thickness(0, 0, 0, 0);

            canv.Background = new SolidColorBrush(Colors.White);

 

            //Rectangle

            Rectangle r = new Rectangle();

            r.Fill = new SolidColorBrush(Colors.Red);

            r.Stroke = new SolidColorBrush(Colors.Red);

            r.Width = 200;

            r.Height = 140;

            r.SetValue(Canvas.LeftProperty, (double)200);

            r.SetValue(Canvas.TopProperty, (double)120);

            canv.Children.Add(r);

            //Ellipse

            Ellipse el = new Ellipse();

            el.Fill = new SolidColorBrush(Colors.Blue);

            el.Stroke = new SolidColorBrush(Colors.Blue);

            el.Width = 240;

            el.Height = 80;

            el.SetValue(Canvas.ZIndexProperty, 1);

            el.SetValue(Canvas.LeftProperty, (double)100);

            el.SetValue(Canvas.TopProperty, (double)80);

            canv.Children.Add(el);

 

        }

 

        private void btnByCode_Click(object sender, RoutedEventArgs e)

        {

            DisplayCanvas();

        }

    }

}

 

 實現後的效果如下圖。

最後 要說明一點Canvas內的子控制元件不能使用兩個以上的Canvas附加屬性,如果同時設定Canvas.Left和Canvas.Right屬性,那麼後者將會被忽略。

2、ZIndex屬性

Canvas面板中可能會有多個相互重疊的元素,可以設定Canvas的ZIndex附加屬性,來控制他們的重疊方式 ZIndex屬性預設值都是0,屬性值必須是整數。

除此之外,我們還可以通過程式碼的方式設定ZIndex的值,程式碼如下:Canvas.SetZIndex(this.btn, 2);

3、測量處理過程(Measure)和排列處理過程(Arrange)