我想知道是否有人知道如何在WPF和VB.Net中复制Flex/flash9片功能。我在Flex中多次使用过9-slice scaling,在WPF中它将是一个很好的资产。我希望能够有一个图像作为我的画布背景,并在不破坏圆角的情况下拉伸它。有谁知道怎么做吗?
发布于 2009-06-02 16:35:16
我不知道有什么内置的功能可以做到这一点,但你可以编写一个自定义控件来做到这一点。
这样的控件的显著部分将是一个9部分网格,其中4部分具有固定大小(角),两部分具有固定的高度和可变的宽度(中心顶部和中心底部),两部分具有固定的宽度和可变的高度(左、中和右),最后的部分具有可变的高度和宽度(中间)。只在一个方向上拉伸(例如,制作一个只水平增长的按钮)就像限制中间部分的高度一样简单。
在XAML中,这将是:
<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):
<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绘制,以便它们显示源图像的正确部分:
<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切片图像控件:
<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切片图像控件中这样做过,但它要复杂得多。
如果我遗漏了什么,请留下评论。
发布于 2009-06-04 15:00:08
这是我辛辛苦苦得到的:
这是SlicedImage.xaml文件:
<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:
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用户控件的用法如下:
<my:SlicedImage ImageLocation="Images/left_bubble.png" Slices="18 25 19 24" />其中ImageLocation是图像位置,Slices是“右上角、左下角”,表示图像的切片方式。所有尺寸都应从左上角开始。
https://stackoverflow.com/questions/939411
复制相似问题