首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF中的9切片图像

WPF中的9切片图像
EN

Stack Overflow用户
提问于 2009-06-02 13:11:02
回答 2查看 2.6K关注 0票数 2

我想知道是否有人知道如何在WPF和VB.Net中复制Flex/flash9片功能。我在Flex中多次使用过9-slice scaling,在WPF中它将是一个很好的资产。我希望能够有一个图像作为我的画布背景,并在不破坏圆角的情况下拉伸它。有谁知道怎么做吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-06-02 16:35:16

我不知道有什么内置的功能可以做到这一点,但你可以编写一个自定义控件来做到这一点。

这样的控件的显著部分将是一个9部分网格,其中4部分具有固定大小(角),两部分具有固定的高度和可变的宽度(中心顶部和中心底部),两部分具有固定的宽度和可变的高度(左、中和右),最后的部分具有可变的高度和宽度(中间)。只在一个方向上拉伸(例如,制作一个只水平增长的按钮)就像限制中间部分的高度一样简单。

在XAML中,这将是:

代码语言:javascript
复制
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="20"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="20"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="20"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="20"/>
    </Grid.RowDefinitions>
</Grid>

然后添加要在其上绘制图像的对象(我将使用矩形),以及要将内容放入其中的对象(ContentPresenter):

代码语言:javascript
复制
<Rectangle Grid.Row="0" Grid.Column="0" x:Name="TopLeft"/>
<Rectangle Grid.Row="0" Grid.Column="1" x:Name="TopCenter"/>
<Rectangle Grid.Row="0" Grid.Column="2" x:Name="TopRight"/>

<Rectangle Grid.Row="1" Grid.Column="0" x:Name="CenterLeft"/>
<Rectangle Grid.Row="1" Grid.Column="2" x:Name="CenterRight"/>

<Rectangle Grid.Row="2" Grid.Column="0" x:Name="BottomLeft"/>
<Rectangle Grid.Row="2" Grid.Column="1" x:Name="BottomCenter"/>
<Rectangle Grid.Row="2" Grid.Column="2" x:Name="BottomRight"/>

<Grid Grid.Row="2" Grid.Column="1" x:Name="Middle">
  <Rectangle/>
  <ContentPresenter x:Name="MiddleContent"/>
</Grid>

每个矩形都可以使用ImageBrush绘制,以便它们显示源图像的正确部分:

代码语言:javascript
复制
<Rectangle>
    <Rectangle.Fill>
        <ImageBrush ImageSource="Image.png" TileMode="None" 
                    <!-- Add the settings necessary to show the correct part of the image --> />
    </Rectangle.Fill>
</Rectangle>

将所有这些打包到一个自定义控件中,您就可以生成一个非常有用的9切片图像控件:

代码语言:javascript
复制
<local:NineSliceImage Image="Source.png" Slice="20,20">
    <TextBox Text="Nine Slice Image TextBox!"/>
</local:NineSliceImage>

其中Slice是一个System.Windows.Size类型的属性,因此您可以使用它来设置切片的位置,就像边距/填充/等属性一样。

您还需要在所有矩形上将SnapToDisplayPixels设置为True;否则,当WPF尝试对中间像素进行插值时,您将在特定分辨率下看到图像各部分之间的小间隙。

如果你打算使用很多这样的控件,另一种更快的方法是重写OnRender并在那里执行;我以前在3切片图像控件中这样做过,但它要复杂得多。

如果我遗漏了什么,请留下评论。

票数 4
EN

Stack Overflow用户

发布于 2009-06-04 15:00:08

这是我辛辛苦苦得到的:

这是SlicedImage.xaml文件:

代码语言:javascript
复制
    <Rectangle Grid.Row="1" Grid.Column="0" SnapsToDevicePixels="True">
        <Rectangle.Fill>
            <ImageBrush x:Name="CenterLeft" Stretch="Fill" ViewboxUnits="Absolute" AlignmentX="Left"  AlignmentY="Center" />
        </Rectangle.Fill>
    </Rectangle>
    <Rectangle Grid.Row="1" Grid.Column="1" SnapsToDevicePixels="True">
        <Rectangle.Fill>
            <ImageBrush x:Name="CenterCenter" Stretch="Fill" ViewboxUnits="Absolute" AlignmentX="Center"  AlignmentY="Center" />
        </Rectangle.Fill>
    </Rectangle>
    <Rectangle Grid.Row="1" Grid.Column="2" SnapsToDevicePixels="True">
        <Rectangle.Fill>
            <ImageBrush x:Name="CenterRight" Stretch="Fill" ViewboxUnits="Absolute" AlignmentX="Right"  AlignmentY="Center" />
        </Rectangle.Fill>
    </Rectangle>

    <Rectangle Grid.Row="2" Grid.Column="0" SnapsToDevicePixels="True">
        <Rectangle.Fill>
            <ImageBrush x:Name="BottomLeft" Stretch="Fill" ViewboxUnits="Absolute" AlignmentX="Left"  AlignmentY="Bottom" />
        </Rectangle.Fill>
    </Rectangle>
    <Rectangle Grid.Row="2" Grid.Column="1" SnapsToDevicePixels="True">
        <Rectangle.Fill>
            <ImageBrush x:Name="BottomCenter" Stretch="Fill" ViewboxUnits="Absolute" AlignmentX="Center"  AlignmentY="Bottom" />
        </Rectangle.Fill>
    </Rectangle>
    <Rectangle Grid.Row="2" Grid.Column="2" SnapsToDevicePixels="True">
        <Rectangle.Fill>
            <ImageBrush x:Name="BottomRight" Stretch="Fill" ViewboxUnits="Absolute" AlignmentX="Right"  AlignmentY="Bottom" />
        </Rectangle.Fill>
    </Rectangle>

</Grid>

</UserControl>

对于那些想要在VB.Net中实现这一点的人,可以使用SlicedImage.xaml.vb:

代码语言:javascript
复制
Partial Public Class SlicedImage
Public imageSource As ImageSource
Public sliceTop As Double
Public sliceRight As Double
Public sliceLeft As Double
Public sliceBottom As Double

Public Sub New()

    InitializeComponent()

End Sub

Public Sub SetViewboxes()
    Dim RealHeight As Double = TopLeft.ImageSource.Height
    Dim RealWidth As Double = TopLeft.ImageSource.Width

    ColumnLeft.Width = New GridLength(sliceLeft)
    ColumnRight.Width = New GridLength(RealWidth - sliceRight)
    RowTop.Height = New GridLength(sliceTop)
    RowBottom.Height = New GridLength(RealHeight - sliceBottom)


    TopLeft.Viewbox = New Rect(0, 0, sliceLeft, sliceTop)
    TopCenter.Viewbox = New Rect(sliceLeft, 0, sliceRight - sliceLeft, sliceTop)
    TopRight.Viewbox = New Rect(sliceRight, 0, RealWidth - sliceRight, sliceTop)

    CenterLeft.Viewbox = New Rect(0, sliceTop, sliceLeft, sliceBottom - sliceTop)
    CenterCenter.Viewbox = New Rect(sliceLeft, sliceTop, sliceRight - sliceLeft, sliceBottom - sliceTop)
    CenterRight.Viewbox = New Rect(sliceRight, sliceTop, RealWidth - sliceRight, sliceBottom - sliceTop)

    BottomLeft.Viewbox = New Rect(0, sliceBottom, sliceLeft, RealHeight - sliceBottom)
    BottomCenter.Viewbox = New Rect(sliceLeft, sliceBottom, sliceRight - sliceLeft, RealHeight - sliceBottom)
    BottomRight.Viewbox = New Rect(sliceRight, sliceBottom, RealWidth - sliceRight, RealHeight - sliceBottom)

End Sub
Public Property ImageLocation() As ImageSource
    Get
        Return Nothing
    End Get
    Set(ByVal value As ImageSource)
        TopLeft.ImageSource = value
        TopCenter.ImageSource = value
        TopRight.ImageSource = value
        CenterLeft.ImageSource = value
        CenterCenter.ImageSource = value
        CenterRight.ImageSource = value
        BottomLeft.ImageSource = value
        BottomCenter.ImageSource = value
        BottomRight.ImageSource = value
    End Set
End Property

Public Property Slices() As String
    Get
        Return Nothing
    End Get
    Set(ByVal value As String)
        Dim sliceArray As Array = value.Split(" ")
        sliceTop = sliceArray(0)
        sliceRight = sliceArray(1)
        sliceBottom = sliceArray(2)
        sliceLeft = sliceArray(3)
        SetViewboxes()
    End Set
End Property

End Class

用户控件的用法如下:

代码语言:javascript
复制
<my:SlicedImage ImageLocation="Images/left_bubble.png" Slices="18 25 19 24" />

其中ImageLocation是图像位置,Slices是“右上角、左下角”,表示图像的切片方式。所有尺寸都应从左上角开始。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/939411

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档