Как создать контейнер WPF с закругленными углами?
-
02-07-2019 - |
Вопрос
Мы создаем приложение XBAP, в котором нам нужны закругленные углы в разных местах на одной странице, и мы хотели бы иметь контейнер WPF с закругленными углами, в котором можно было бы разместить множество других элементов.Есть ли у кого-нибудь предложения или примеры кода о том, как лучше всего это сделать?Либо со стилями, либо с созданием пользовательского элемента управления?
Решение
Вам не нужен специальный элемент управления, просто поместите контейнер в элемент границы:
<Border BorderBrush="#FF000000" BorderThickness="1" CornerRadius="8">
<Grid/>
</Border>
Вы можете заменить <Grid/>
с любым из контейнеров макета...
Другие советы
Я знаю, что это не ответ на первоначальный вопрос...но часто требуется обрезать внутреннее содержимое только что созданной границы с закругленными углами.
Крис Кавана придумал отличный способ сделать именно это.
Я попробовал несколько разных подходов к этому...и я думаю, что это потрясающе.
Вот xaml ниже:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Black"
>
<!-- Rounded yellow border -->
<Border
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="Yellow"
BorderThickness="3"
CornerRadius="10"
Padding="2"
>
<Grid>
<!-- Rounded mask (stretches to fill Grid) -->
<Border
Name="mask"
Background="White"
CornerRadius="7"
/>
<!-- Main content container -->
<StackPanel>
<!-- Use a VisualBrush of 'mask' as the opacity mask -->
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
<!-- Any content -->
<Image Source="http://chriscavanagh.files.wordpress.com/2006/12/chriss-blog-banner.jpg"/>
<Rectangle
Height="50"
Fill="Red"/>
<Rectangle
Height="50"
Fill="White"/>
<Rectangle
Height="50"
Fill="Blue"/>
</StackPanel>
</Grid>
</Border>
</Page>
Мне просто нужно было сделать это самому, поэтому я решил опубликовать здесь еще один ответ.
Вот еще один способ создать границу с закругленным углом. и обрезать его внутреннее содержимое.Это простой способ использования свойства Clip.Хорошо, если вы хотите избежать использования VisualBrush.
Ксамл:
<Border
Width="200"
Height="25"
CornerRadius="11"
Background="#FF919194"
>
<Border.Clip>
<RectangleGeometry
RadiusX="{Binding CornerRadius.TopLeft, RelativeSource={RelativeSource AncestorType={x:Type Border}}}"
RadiusY="{Binding RadiusX, RelativeSource={RelativeSource Self}}"
>
<RectangleGeometry.Rect>
<MultiBinding
Converter="{StaticResource widthAndHeightToRectConverter}"
>
<Binding
Path="ActualWidth"
RelativeSource="{RelativeSource AncestorType={x:Type Border}}"
/>
<Binding
Path="ActualHeight"
RelativeSource="{RelativeSource AncestorType={x:Type Border}}"
/>
</MultiBinding>
</RectangleGeometry.Rect>
</RectangleGeometry>
</Border.Clip>
<Rectangle
Width="100"
Height="100"
Fill="Blue"
HorizontalAlignment="Left"
VerticalAlignment="Center"
/>
</Border>
Код конвертера:
public class WidthAndHeightToRectConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double width = (double)values[0];
double height = (double)values[1];
return new Rect(0, 0, width, height);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Реализация решения kobusb для пограничного контроля на основе кода VB.Net.Я использовал его для заполнения ListBox элементов управления Button.Элементы управления Button созданы на основе расширений MEF.Каждое расширение использует атрибут ExportMetaData MEF для описания расширения.Расширения представляют собой объекты диаграмм VisiFire.Пользователь нажимает кнопку, выбранную из списка кнопок, для выполнения нужного графика.
' Create a ListBox of Buttons, one button for each MEF charting component.
For Each c As Lazy(Of ICharts, IDictionary(Of String, Object)) In ext.ChartDescriptions
Dim brdr As New Border
brdr.BorderBrush = Brushes.Black
brdr.BorderThickness = New Thickness(2, 2, 2, 2)
brdr.CornerRadius = New CornerRadius(8, 8, 8, 8)
Dim btn As New Button
AddHandler btn.Click, AddressOf GenericButtonClick
brdr.Child = btn
brdr.Background = btn.Background
btn.Margin = brdr.BorderThickness
btn.Width = ChartsLBx.ActualWidth - 22
btn.BorderThickness = New Thickness(0, 0, 0, 0)
btn.Height = 22
btn.Content = c.Metadata("Description")
btn.Tag = c
btn.ToolTip = "Push button to see " & c.Metadata("Description").ToString & " chart"
Dim lbi As New ListBoxItem
lbi.Content = brdr
ChartsLBx.Items.Add(lbi)
Next
Public Event Click As RoutedEventHandler
Private Sub GenericButtonClick(sender As Object, e As RoutedEventArgs)
Dim btn As Button = DirectCast(sender, Button)
Dim c As Lazy(Of ICharts, IDictionary(Of String, Object)) = DirectCast(btn.Tag, Lazy(Of ICharts, IDictionary(Of String, Object)))
Dim w As Window = DirectCast(c.Value, Window)
Dim cc As ICharts = DirectCast(c.Value, ICharts)
c.Value.CreateChart()
w.Show()
End Sub
<System.ComponentModel.Composition.Export(GetType(ICharts))> _
<System.ComponentModel.Composition.ExportMetadata("Description", "Data vs. Time")> _
Public Class DataTimeChart
Implements ICharts
Public Sub CreateChart() Implements ICharts.CreateChart
End Sub
End Class
Public Interface ICharts
Sub CreateChart()
End Interface
Public Class Extensibility
Public Sub New()
Dim catalog As New AggregateCatalog()
catalog.Catalogs.Add(New AssemblyCatalog(GetType(Extensibility).Assembly))
'Create the CompositionContainer with the parts in the catalog
ChartContainer = New CompositionContainer(catalog)
Try
ChartContainer.ComposeParts(Me)
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
' must use Lazy otherwise instantiation of Window will hold open app. Otherwise must specify Shutdown Mode of "Shutdown on Main Window".
<ImportMany()> _
Public Property ChartDescriptions As IEnumerable(Of Lazy(Of ICharts, IDictionary(Of String, Object)))
End Class
Если вы пытаетесь поместить кнопку в рамку с закругленным прямоугольником, вам следует проверить пример MSDN.Я нашел это, погуглив изображения проблемы (вместо текста).Их громоздкий внешний прямоугольник (к счастью) легко снять.
Обратите внимание, что вам придется переопределить поведение кнопки (поскольку вы изменили ControlTemplate).То есть вам нужно будет определить поведение кнопки при нажатии с помощью тега Trigger (Property="IsPressed" Value="true") в теге ControlTemplate.Triggers.Надеюсь, это сэкономит кому-нибудь время, которое я потерял :)