visual tutorial studio hechas ejemplos crear controles aplicaciones aplicacion wpf rounded-corners

tutorial - ¿Cómo creo un contenedor de esquina redondeada de WPF?



visual studio wpf (5)

Estamos creando una aplicación XBAP que necesitamos para tener esquinas redondeadas en varias ubicaciones en una sola página y nos gustaría tener un contenedor de esquina redondeada WPF para colocar un montón de otros elementos dentro. ¿Alguien tiene alguna sugerencia o código de muestra sobre cómo podemos lograr esto de la mejor manera? ¿Ya sea con estilos en o con crear un control personalizado?


Implementación basada en el código VB.Net de la solución de control de fronteras de kobusb. Lo utilicé para poblar un cuadro de lista de controles de botón. Los controles del botón se crean a partir de extensiones MEF. Cada extensión usa el atributo ExportMetaData de MEF para una Descripción de la extensión. Las extensiones son objetos de gráficos VisiFire. El usuario presiona un botón, seleccionado de la lista de botones, para ejecutar el gráfico deseado.

'' 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


No necesita un control personalizado, simplemente coloque su contenedor en un elemento de borde:

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" CornerRadius="8,8,8,8"> <Grid/> </Border>

Puede reemplazar la <Grid/> con cualquiera de los contenedores de disposición ...


Sé que esta no es una respuesta a la pregunta inicial ... pero a menudo quiere recortar el contenido interno de ese borde de esquina redondeado que acaba de crear.

Chris Cavanagh ha ideado una forma excelente de hacer esto.

He intentado un par de enfoques diferentes a esto ... y creo que este es un problema.

Aquí está el xaml a continuación:

<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>


Si intentas poner un botón en un borde de rectángulo redondeado, debes echar un vistazo al ejemplo de msdn . Encontré esto buscando en Google imágenes del problema (en lugar de texto). Su voluminoso rectángulo externo es (afortunadamente) fácil de quitar.

Tenga en cuenta que deberá redefinir el comportamiento del botón (ya que ha cambiado ControlTemplate). Es decir, deberá definir el comportamiento del botón al hacer clic con una etiqueta Trigger (Property = "IsPressed" Value = "true") en la etiqueta ControlTemplate.Triggers. Espero que esto le ahorre a otra persona el tiempo que perdí :)


Solo tenía que hacer esto yo mismo, así que pensé en publicar otra respuesta aquí.

Aquí hay otra forma de crear un borde de esquina redondeada y recortar su contenido interno . Esta es la forma directa de usar la propiedad Clip. Es bueno si quieres evitar un VisualBrush.

El 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>

El código para el convertidor:

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(); } }