【WPF學習】第四十章 畫刷

  畫刷填充區域,無論是元素的背景色、前景色以及邊框,仍是形狀的內部填充和筆畫(Stroke)。最簡單的畫刷類型是SolidColorBrush,這種畫刷填充一種固定、連續的顏色。在XAML中設置形狀的Stroke或Fill屬性時,使用的是SolidColorBrush畫刷,他們在後臺完成繪製。緩存

  下面是幾個與畫刷相關的更基本的方面:app

  •   畫刷支持更改通知,由於他們繼承自Freezable類。所以,若是改變了畫刷,任何使用畫刷的元素都會自動從新繪製自身。
  •   畫刷支持部分透明。爲此,只須要修改Opacity屬性,使背景可以透過前面的內容進行顯示。
  •   經過SystemBrushes類能夠訪問這樣的畫刷:此類畫刷使用Windows系統設置爲當前計算機定義的首選顏色。

  SolidColorBrush畫刷無疑很是有用,但還有其餘幾個繼承自System.Windows.Media.Brush的類,經過這些類可獲得更新穎的效果。下表列出了全部這些類。ide

表 畫刷類動畫

 1、SolidColorBrush畫刷this

   在大多數控件中,經過設置Foreground屬性繪製文本顏色,並設置Background屬性繪製文本背後的空間。形狀使用相似但不一樣的屬性:Stroke屬性用於繪製形狀的邊框,而Fill屬性用於繪製形狀的內部。spa

  可在XAML中使用顏色名設置Stroke和Fill屬性,對於這種狀況,WPF解析器自動建立匹配的SolidColorBrush對象。也可使用代碼設置Stroke和Fill屬性,但須要顯示地建立SolidColorBrush對象。code

//Create a brush from a named color:
cmd.Background=new SolidColorBrush(Colors.AliceBlue);

//Create a brush from a system color:
cmd.Background=SystemColors.ControlBrush;

//Create a brush from color values:
int red=0;int green=255; int blue=0;
cmd.Foreground=new SolidColorBrush(Color.FromRgb(red,green,blue));

2、LinearGradientBrush畫刷orm

  可經過LinearGradientBrush畫刷建立從一種顏色變化到另外一種顏色的混合填充。xml

  下面多是最簡單的漸變。該漸變從藍色(左上角)到白色(右下角)在對角線上對矩形進行着色。對象

<Rectangle Width="150" Height="100" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush >
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

  爲建立這種漸變效果,須要爲每種顏色添加一個GradientStop對象,還須要在漸變中使用0~1的偏移值放置每種顏色。在該例中,用於藍色的GradientStop對象的偏移值爲0,這意味着它被放在漸變的開頭。用於白色的GradientStop對象的偏移值爲1,這意味着將它放在末尾。經過改變這些值,可調整漸變從一種顏色變化到另外一種顏色的速度。例如,若是將白色的GradientStop設置爲0.5,漸變就會在中間(兩個拐角的中點)從藍色(左上角)混合到白色。矩形的右邊將會是純白色的。

  上面的標記建立了從一個拐角拉伸到另外一個拐角的對象填充漸變。然而,可能但願建立自上而下或從一邊向另外一邊混合的漸變,或是使用不一樣的對角線角度。可以使用LinearGradientBrush的StartPoint和EndPoint屬性控制這些細節。能夠經過這些屬性選擇第一種顏色開始變化的點,以及最後一種顏色結束變化的點(中間的區域被漸變混合)。但這裏存在一個古怪的問題:用於開始點和結束點的座標不是真實座標。相反,LinearGradientBrush畫刷將點(0,0)指定爲但願但願填充的區域的左上角,將點(1,1)指定爲但願填充的區域的右下角,而無論該區域實際上有多高和多寬。

  爲建立自上而下的橫向填充,可將用於左上角的(0,0)點做爲開始點,並將(0,1)點做爲結束點,該點表示左下角。爲了建立從一邊到另外一邊的垂直填充(不傾斜),可使用點(0,0)做爲開始點,並使用右上角的點(1,0)做爲結束點。

  經過爲漸變提供不是填充區域拐角點的開始點和結束點。可獲得更靈活的漸變。例如,漸變可從點(0,0)拉伸到點(0,0.5),該點是左側邊緣上的中點。這會建立壓縮的線性漸變——一種顏色從頂部開始,在中間混合到第二種顏色。形狀的後半部分使用第二種顏色。但可用LinearGradientBrush.SpreadMethod屬性改變這種行爲。默認狀況下,該屬性使用Pad(這意味着漸變以外的區域使用恰當的純色填充),但也可以使用Reflect(翻轉漸變,從第二種顏色反向漸變大偶第一種顏色)或Repeat(複製相同的顏色變化過程)。

  LinearGradientBrush畫刷還可經過添加兩個以上的GradientStop對象,建立具備兩種以上的顏色漸變。例如,下面的漸變實現了彩虹效果:

<Rectangle Width="150" Height="100" Grid.Row="4" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

  惟一的技巧是爲每一個GradientStop對象何止合適的偏移值。例如,若是但願變換通過5中顏色,可將第1中顏色的偏移值設置爲0,第2中顏色的偏移值設置爲0.25,將第3中顏色的偏移值設置爲0.5,第4種顏色的偏移值設置爲0.75,將第5中顏色的偏移值設置爲1。或者若是但願開始時漸變速度較快,而在結束速度較慢,可將便宜值設置爲0、0.一、0.二、0.四、0.六、1。

  下面是LinearGradientBrush畫刷的完整示例以及效果圖:

<Window x:Class="Drawing.Gradients"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Gradients" Height="587" Width="347">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <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></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Rectangle Width="150" Height="100" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush >
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="5">Diagonal Linear Gradient</TextBlock>

        <Rectangle Width="150" Height="100" Margin="5" Grid.Row="1">
            <Rectangle.Fill>
                <LinearGradientBrush>
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="0.5" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5">With 0.5 Offset for White</TextBlock>

        <Rectangle Width="150" Height="100" Grid.Row="2" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="5">Horizontal Linear Gradient</TextBlock>

        <Rectangle Width="150" Height="100" Grid.Row="3" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,0.5" SpreadMethod="Reflect">
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Margin="5">Reflected Gradient</TextBlock>

        <Rectangle Width="150" Height="100" Grid.Row="4" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" Margin="5">Multicolored Gradient</TextBlock>
    </Grid>
</Window>
Gradients

 

   漸變畫刷並不限於繪製形狀。可在使用SolidColorBrush畫刷的任什麼時候候替代LinearGradientBrush——例如,填充元素的背景表面(使用Background屬性)、填充元素文本的前景色(使用Foreground屬性)或者填充邊框(使用BorderBrush屬性)。以下示例所示:

<Window x:Class="Drawing.GradientText"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="GradientText" Height="300" Width="300">
    <Grid>
        <TextBlock Margin="5"  FontWeight="Bold" FontSize="65" TextWrapping="Wrap" TextAlignment="Center">
            <TextBlock.Text>This text uses a gradient.</TextBlock.Text>
            <TextBlock.Foreground>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </TextBlock.Foreground>
        </TextBlock>
    </Grid>
</Window>
GradientText

3、RadialGradientBrush畫刷

  RadialGradientBrush畫刷和LinearGradientBrush畫刷的工做方式相似,也使用一系列具備不一樣偏移值的顏色。與LinearGradientBrush畫刷同樣,可以使用但願的任意多種顏色。區域是放置漸變的方式。

  爲指定第一種顏色在漸變中的開始點,須要使用GradientOrigin屬性。默認狀況下,漸變的開始點是(0.5,0.5),該點表示填充區域的中心。

  漸變從開始點以環形的方式向外輻射。漸變最終到達內部漸變圓的邊緣,這裏是漸變的終點。根據所指望的效果,漸變圓的中心可能和漸變開始點對齊,也可能和漸變開始點不對齊。超出內部漸變圓的區域以及填充區域的最外側邊緣。使用在RadialGradientBrush.GradientStops集合中定義的最後一種顏色進行純色填充。

  可以使用三個屬性設置內部漸變圓的邊界:Center、RadiusX和RadiusY。默認狀況下,Center屬性被設置爲(0.5,0.5),該設置將限定圓的中心放在填充區域的中央,而且該點同時也是漸變開始點。

  RadiusX和RadiusY屬性 決定了限定圓的尺寸,默認狀況下着兩個屬性都被設置爲0.5.這些值可能不夠直觀,由於他們根據填充區域的對角範圍(一條從填充區域的左上角延伸到右下角的假想線的長度)進行度量。這意味着半徑0.5定義了一個圓,該圓的半徑是對角線長度的一半。若是填充區域爲正方形,使用勾股定理可計算出,該長度大約是填充區域寬度(或寬度)的0.7倍。所以,若是用默認設置填充正方形區域,漸變就從中心點開始,並拉伸大約正方形寬度0.7倍的距離到達最外側邊界。

  對於填充圓形形狀並建立發光效果,徑向漸變是很是好的選擇(水平高超的美工人員經過組合使用漸變建立具備光暈效果的按鈕)。一種常見技巧是稍微偏移GradientOrigin點,爲形狀建立深度感。

<Window x:Class="Drawing.RadialGradient"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RadialGradient" Height="534" Width="480">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Ellipse Margin="5" Stroke="Black" StrokeThickness="1">
            <Ellipse.Fill>
                <RadialGradientBrush RadiusX="1" RadiusY="1" >
                    <GradientStop Color="White" Offset="0"/>
                    <GradientStop Color="Blue" Offset="1"/>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
        <TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="5">A Radial Gradient</TextBlock>

        <Ellipse Margin="5" Grid.Row="1" Stroke="Black" StrokeThickness="1">
            <Ellipse.Fill>
                <RadialGradientBrush
             RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3"
            >
                    <GradientStop Color="White" Offset="0" />
                    <GradientStop Color="Blue" Offset="1" />
                </RadialGradientBrush>

            </Ellipse.Fill>
        </Ellipse>
        <TextBlock Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5" TextWrapping="Wrap">A Radial Gradient with an Offset Center</TextBlock>

    </Grid>
</Window>
RadialGradient

 

 4、ImageBrush畫刷

  可經過ImageBrush畫刷使用位圖填充區域。可以使用最多見的文件類型,包括BMP、PNG、GIF以及JPEG文件。可經過設置ImageSource屬性來制定但願使用的圖像。例如,下面的畫刷使用一幅名爲logo.jpg的圖像繪製Grid面板的背景,在程序集中做爲資源包含了該圖像:

<Grid>
        <Grid.Background>
            <ImageBrush  ImageSource="logo.jpg" />
        </Grid.Background>    
    </Grid>

  ImageBrush.ImageSource屬性和Image元素的Source屬性的工做方式相同,這意味着也可使用指向資源、外部文件或Web站點的URI設置ImageSource屬性。也可經過爲ImageSource屬性提供DrawingImage對象,建立使用由XAML定義的矢量內容的ImageBrush畫刷。可經過這種方法下降開銷(經過避免使用更耗資源的Shape類的派生類),或使用矢量圖像建立平鋪模式。

  在該例中,ImageBrush畫刷用於繪製單元格的背景。所以,爲了適應填充區域,圖像會被拉伸。若是Grid面板比圖像的原始尺寸大,就會看到改變圖像尺寸形成的顯示問題(如常見的模糊效果)。若是Grid面板的形狀和圖像的寬高比不匹配,爲了適應Grid面板,圖像會變形。

  爲控制該行爲,可修改ImageBrush.Stretch屬性。例如,可將該屬性設置爲Uniform,從而爲了適應縮放圖像時保持圖像的高寬比,或將該屬性設置爲None,使用圖像的天然尺寸繪製圖像(對於這種狀況,爲適應容器,部分圖像可能被裁減掉)。

  若是繪製的圖像比填充區域小,圖像會根據AlignmentX和AlignmentY屬性進行對齊。未填充的區域保持透明。當使用Uniform設置進行縮放,而且填充區域的形狀不一樣時,就會出現這種狀況。若是將Stretch屬性設置爲None,而且填充區域比圖像大,也會出現這種狀況。

  還可以使用Viewbox屬性從圖像上裁剪有興趣使用的一小部分。爲此,須要指定4個數值以描述但願從源圖上裁剪並使用的矩形部分。前連個數值指定矩形開始的左上角,然後兩個數值指定矩形的寬度和高度。惟一的問題是Viewbox屬性使用的是相對座標系統,就像漸變畫刷使用的座標系統那樣。這一座標系統將圖像上的左上角指定爲(0,0),將右下角指定爲(1,1)。

  爲理解Viewbox屬性的工做原理,分析下面的標記:

<ImageBrush ImageSource="logo.jpg" Stretch="Uniform"
    Viewbox="0.4 0.5 0.2 0.2"></ImageBrush>

  如今,Viewbox屬性從(0.4,0.5)開始,這差很少是用圖像的一半出開始(從技術角度看,X座標是寬度的0.4倍,Y座標是高度的0.5倍)。而後伸展矩形以填充一個20%寬度和20%高度的小方塊做爲整幅圖像(從技術角度看,矩形的長度爲圖像寬度的0.2倍,矩形的高度爲圖像高度的0.2倍)。根據Stretch、AlignmentX以及AlignmentY屬性的設置,被裁剪下來的部分圖像會被拉伸或劇中顯示。下圖顯示兩個使用不一樣ImageBrush對象填充自身的矩形。最上面的矩形顯示了整幅圖像,下面的矩形使用Viewbox放大了圖像中的一小部分。這兩個矩形都使用了純黑色的邊框。

<Window x:Class="Drawing.ImageBrushes"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ImageBrushes" Height="389.6" Width="419.6">
    <Canvas>
        <Rectangle Canvas.Left="10" Canvas.Top="10"  Width="271" Height="100" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="logo.jpg" Stretch="Fill"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Canvas.Left="10" Canvas.Top="120" Width="200" Height="200" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="logo.jpg" Stretch="Uniform"
    Viewbox="0.4 0.5 0.2 0.2"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Canvas>
</Window>
ImageBrushes

 

 5、平鋪的ImageBrush畫刷

  除廣泛的ImageBrush畫刷外,還有其餘使人更加激動的內容。可經過在畫刷的表面平鋪圖像來獲得一些有趣的效果。

  當平鋪圖像時,有兩種選擇:

  •   按比例平鋪。填充區域始終具備相同數量的平鋪圖像。爲適應填充區域,平鋪的圖像會擴展或收縮。
  •   按固定尺寸平鋪。平鋪圖像始終具備相同的尺寸。填充區域的尺寸決定了顯示的平鋪圖像的數量。

  爲了平鋪一幅圖像,須要設置ImageSource屬性(指定但願平鋪的圖像)以及ViewPort、ViewportUnits與TitleMode屬性。後三個屬性決定了平鋪圖像的尺寸和排列方式。

  可以使用Viewport屬性設置每幅平鋪圖像的尺寸。爲使用按比例平鋪模式,必須將ViewportUnits屬性這是爲RelativeToBoundingBox(默認值)。而後使用在兩個方向上的座標範圍都是從0到1的按比例座標定義平鋪圖像的尺寸。換句話說,若是一幅平鋪圖像的左上角位於(0,0),右下角位於(1,1),就會佔據整個填充區域。爲獲得平鋪模式,爲Viewport屬性設置的值應當比整個填充區域的尺寸小。以下所示:

<ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                     Viewport="0 0 0.5 0.5"></ImageBrush>

  上面的標記建立了一個從填充區域的左上角(0,0)開始,並拉伸到中間點(0.5,0.5)的Viewport方框。所以,無論填充區域的大小如何,填充區域始終包含4幅平鋪圖像。這樣行爲很是好,由於可確保平鋪圖像不會在形狀的邊緣被裁減(固然,若是使用ImageBrush畫刷填充非矩形區域,圖像仍會被裁剪)。

  由於這個示例中的平鋪圖像採用相對於填充區域的尺寸,因此更大的填充區域會使用更大的平鋪圖像,而且由於改變了圖像的尺寸。因此會形成必定的模糊效果。此外,若是填充區域不是完美的正方形,相對座標系統會相應地進行行擠壓,從而每一個平鋪的正方形都會變成矩形。

  可經過修改Stretch屬性(默認設置爲Fill)改變這種行爲。若是將該屬性設置爲None,可保證平鋪圖像永不變形,而且保持正確的形狀,然而,若是填充區域不是正方形,將在平鋪圖像之間顯示空白空間。

  第三種選擇是將Stretch屬性設置爲UniformToFill這種設置會根據須要裁減平鋪的圖像。使用這種方式,平鋪圖像會保持正確的縱橫比,並且平鋪的圖像之間沒有空白空間。然而,若是填充的區域不是正方形,就不會看到完整的平鋪圖像。

  自動改變平鋪圖像的尺寸是一項很是有用的功能,但也是須要付出代價。有些位圖可能不能正確地改變其尺寸。在某種程度上,可經過提供比所需位圖更大的位圖,爲應對這種狀況作好準備。噹噹縮小圖像時,這種技術就會致使更模糊的位圖。

  另外一種定義平鋪圖像的尺寸的方法是根據原始圖像的尺寸使用絕對座標。爲此,將ViewportUnits屬性設置爲Absolute。下面舉一個示例,該例將每幅平鋪圖像定義爲32X32單位大小,並從左上角開始平鋪:

<ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                            ViewboxUnits="Absolute" Viewbox="0 0 32 32"/>

  這種模式的缺點就是填充區域的高度和寬度必須能被32整除。不然,在填充區域便於就會顯示部分平鋪圖像。若是使用ImageBrush畫刷填充可改變尺寸的元素,就沒法避免該問題,因此必須接受平鋪圖像未必能與填充區域的邊緣對齊這種狀況。

  下面是上面示例的完整XAML:

<Window x:Class="Drawing.TileTypes"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TileTypes" Height="500" Width="296.8">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <TextBlock Margin="3">固定尺寸<LineBreak></LineBreak>平鋪</TextBlock>
        <Rectangle Grid.Column="1" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                            ViewboxUnits="Absolute" Viewbox="0 0 32 32"/>
            </Rectangle.Fill>
        </Rectangle>

        <TextBlock Grid.Row="1" Margin="3">按比例<LineBreak></LineBreak>平鋪</TextBlock>
        <Rectangle Grid.Row="1" Grid.Column="1" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                     Viewport="0 0 0.5 0.5"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>

        <TextBlock Grid.Row="2" Margin="3">
      按比例<LineBreak></LineBreak>平鋪(無拉伸)
        </TextBlock>
        <Rectangle Grid.Row="2" Grid.Column="1" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="tile.jpg" TileMode="Tile" Stretch="None"
                    Viewport="0 0 0.5 0.5"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Grid>
</Window>
TileTypes

  下表列出了TileMode枚舉值得全部選項.

表 TileMode枚舉值

 

   若是須要 使平鋪圖像更無縫地混合,翻轉行爲一般是有用的。例如,若是使用FlipX,相鄰的平鋪圖像總能夠無縫地排列。下面舉例說明一下。

<Window x:Class="Drawing.TileFlip"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TileFlip" Height="300" Width="300">
    <!-- Overlay labels by putting one UniformGrid on top of another. -->
    <Grid>
        <UniformGrid>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="Tile" 
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="FlipX"
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="FlipY"
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="FlipXY"
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
        </UniformGrid>
        <UniformGrid>
            <UniformGrid.Resources>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="HorizontalAlignment" Value="Center"></Setter>
                    <Setter Property="VerticalAlignment" Value="Bottom"></Setter>
                    <Setter Property="FontSize" Value="25"></Setter>
                    <Setter Property="FontWeight" Value="Bold"></Setter>
                    <Setter Property="Margin" Value="3"></Setter>
                </Style>
            </UniformGrid.Resources>
            <TextBlock>Tile</TextBlock>
            <TextBlock>FlipX</TextBlock>
            <TextBlock>FlipY</TextBlock>
            <TextBlock>FlipXY</TextBlock>
        </UniformGrid>
    </Grid>
</Window>
TileFlip

 

 6、VisualBrush畫刷

  VisualBrush畫刷不經常使用,使用這種畫刷獲取元素的可視化內容,並使用該內容填充任意表面。例如,可以使用VisualBrush畫刷將窗口中某個按鈕的外觀複製到同一個窗口中的其餘位置。然而,複製的按鈕不能被單擊,也不能經過任何方式與其進行交互。在此就複製了元素的外觀。例如,下面的標記片斷定義了一個按鈕和用於複製該按鈕的VisualBrush畫刷:

 <Button Name="cmd" Margin="3" Padding="5">Is this a real button?</Button>
        <Rectangle Margin="3" Height="{Binding ElementName=cmd,Path=ActualHeight}">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
</Rectangle>

  儘管可在VisualBrush自己定義但願使用的元素,但一般使用綁定表達式引用當前窗口中的額元素。如本例所示,下圖顯示了原始按鈕(在窗口頂部)和幾個形狀不一樣的區域,這些區域是用基於按鈕的VisualBrush畫刷繪製的。完整XAML以下所示:

<Window x:Class="Drawing.VisualBrush"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="VisualBrush" Height="300" Width="300">
    <StackPanel Margin="3">
        <Button Name="cmd" Margin="3" Padding="5">Is this a real button?</Button>
        <Rectangle Margin="3" Height="{Binding ElementName=cmd,Path=ActualHeight}">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Margin="3" Height="50">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Margin="3" Height="150">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
    </StackPanel>
</Window>
VisualBrush

 

   VisualBrush監視元素外觀的變化。例如,若是複製某個按鈕的可視化外觀,並且此外按鈕收到焦點,VisualBrush畫刷會使用新的可視化內容從新繪製填充區域——一個具備焦點的按鈕。VisualBrush類繼承自TileBrush類,所以,VisualBrush類也支持全部的裁剪、拉伸以及翻轉等特性。

7、BitmapCacheBrush畫刷

  BitmapCacheBrush畫刷在許多方面和VisualBrush畫刷相似。儘管VisualBrush類提供了用於引用其餘元素的Visual屬性,但BitmapCacheBrush類提供了與此做用相同的Target屬性。

  二者之間的關鍵區別是,BitmapCacheBrush畫刷採用可視化內容(這些內容以及經過變換、裁剪、效果以及透明設置進行了改變)並要求顯卡在顯存中存儲該內容。這樣一來,當須要時可快速地從新繪製內容,而沒必要要求WPF執行任何額外的工做。

  爲配置位圖緩存,設置BitmapCacheBrush.BitmapCache屬性(使用可預先肯定的BitmapCache對象)。下面是最簡單的用法:

<Button Name="cmd" Margin="3" Padding="5">Is this a real button?</Button>
        <Rectangle Margin="3" Height="{Binding ElementName=cmd,Path=ActualHeight}">
            <Rectangle.Fill>
                <BitmapCacheBrush Target="{Binding ElementName=cmd}">
                </BitmapCacheBrush>
            </Rectangle.Fill>
        </Rectangle>

  BitmapCacheBrush畫刷存在嚴重缺點:渲染位圖以及將其複製到顯存的初始化步驟須要比較短但可察覺到得額外時間。若是在窗口中使用BitmapCacheBrush畫刷,在窗口第一次繪製自身以前,當渲染BitmapCacheBrush並複製其位圖時,將會注意到延遲。所以,在傳統窗口中,BitmapCacheBrush起不到多大的幫助做用。

  然而,若是在用戶界面中大量使用動畫,值得考慮使用位圖緩存。這是由於動畫會強制窗口在沒一秒內從新繪製屢次。若是具備複雜的矢量內容,從緩存位圖中繪製窗口內容比從頭從新繪製窗口要快。但即便是這種狀況,也不該當當即使用BitmapCacheBrush畫刷。可能更願意經過爲每一個但願緩存的元素設置更高級的UIElement.CacheMode屬性來應用緩存。對於這種狀況,WPF在後臺使用BitmapCacheBrush畫刷獲取相同的效果,但須要作的工做更少。

  根據這些細節,BitmapCacheBrush畫刷自己好像不是頗有用。然而,若是須要在幾個地方繪製單塊複雜的可視化內容,使用BitmapCacheBrush畫刷是合理的。對於這種狀況,經過使用BitmapCacheBrush畫刷緩存整個可視化內容比單獨緩存每一個元素更節省內存。在此輸出,這種節省可能得不償失,除非用戶界面還使用了動畫。

相關文章
相關標籤/搜索