Como faço para criar um recipiente WPF arredondado Corner?
-
02-07-2019 - |
Pergunta
Estamos criando um aplicativo XBAP que precisamos ter cantos arredondados em vários locais em uma única página e gostaríamos de ter um recipiente WPF canto arredondado para colocar um monte de outros elementos dentro. Alguém tem algumas sugestões ou código de exemplo sobre como podemos melhor alcançar este objetivo? Ou com estilos em um ou com a criação de um controle personalizado?
Solução
Você não precisa de um controle personalizado, basta colocar o recipiente em um elemento de fronteira:
<Border BorderBrush="#FF000000" BorderThickness="1" CornerRadius="8">
<Grid/>
</Border>
Você pode substituir o <Grid/>
com qualquer um dos recipientes de layout ...
Outras dicas
Eu sei que isso não é uma resposta para a pergunta inicial ... mas muitas vezes você quer cortar o conteúdo interno dessa fronteira canto arredondado que você acabou de criar.
Chris Cavanagh surgiu com um excelente maneira para fazer exatamente isso.
Eu tentei um par diferentes abordagens a este ... e eu acho que este rochas.
Aqui está o XAML abaixo:
<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>
Eu apenas tive que fazer isso sozinho, então eu pensei que eu ia postar outra resposta aqui.
Aqui é outra maneira de criar uma borda de canto arredondado e clipe seu conteúdo interno . Esta é a maneira simples, usando a propriedade Clip. É bom se você quer evitar um VisualBrush.
O XAML:
<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>
O código para o conversor:
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();
}
}
VB.Net código de implementação base da solução de controlo fronteiriço de kobusb. Usei-o para preencher uma caixa de listagem de controles Button. Os controles Button são criados a partir de extensões MEF. Cada extensão usa atributo ExportMetaData do MEF para uma descrição da extensão. As extensões são Visifire mapear objetos. O usuário aperta um botão, selecionados a partir da lista de botões, para executar o gráfico desejado.
' 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
Se você está tentando colocar um botão em uma borda arredondada-retângulo, você deve verificar MSDN exemplo . Achei isso por googling para imagens do problema (em vez de texto). Sua retângulo externo volumoso é (felizmente) fácil de remover.
Note que você terá que redefinir o comportamento do botão (desde que você mudou o ControlTemplate). Ou seja, você precisará definir o comportamento do botão quando clicado usando uma tag gatilho (Propriedade = "IsPressed" Value = "true") na tag ControlTemplate.Triggers. Esperamos que esta salva alguém o tempo que perdi:)