Come si crea un contenitore WPF Rounded Corner?
-
02-07-2019 - |
Domanda
Stiamo creando un'applicazione XBAP che dobbiamo avere angoli arrotondati in varie posizioni in una singola pagina e vorremmo avere un contenitore WPF Rounded Corner per posizionare un gruppo di altri elementi all'interno. Qualcuno ha qualche suggerimento o codice di esempio su come possiamo farlo al meglio? O con gli stili su o con la creazione di un controllo personalizzato?
Soluzione
Non è necessario un controllo personalizzato, basta inserire il contenitore in un elemento bordo:
<Border BorderBrush="#FF000000" BorderThickness="1" CornerRadius="8">
<Grid/>
</Border>
Puoi sostituire <Grid/>
con uno qualsiasi dei contenitori di layout ...
Altri suggerimenti
So che questa non è una risposta alla domanda iniziale ... ma spesso vuoi ritagliare il contenuto interno di quel bordo arrotondato che hai appena creato.
Chris Cavanagh ha ideato un modo eccellente di fare proprio questo.
Ho provato un paio di approcci diversi a questo ... e penso che questo sbalzi.
Ecco lo xaml di seguito:
<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>
Ho dovuto farlo da solo, quindi ho pensato di pubblicare un'altra risposta qui.
Ecco un altro modo per creare un bordo dell'angolo arrotondato e ritagliarne il contenuto interno . Questo è il modo più semplice usando la proprietà Clip. È bello se vuoi evitare un VisualBrush.
Il 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>
Il codice per il convertitore:
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();
}
}
Implementazione basata su codice VB.Net della soluzione di controllo di frontiera di kobusb. L'ho usato per popolare un ListBox di controlli Button. I controlli Button sono creati dalle estensioni MEF. Ogni estensione utilizza l'attributo ExportMetaData di MEF per una descrizione dell'estensione. Le estensioni sono oggetti grafici VisiFire. L'utente preme un pulsante, selezionato dall'elenco di pulsanti, per eseguire il grafico desiderato.
' 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 stai provando a inserire un pulsante in un bordo con rettangolo arrotondato, dai un'occhiata a esempio di msdn . Ho trovato questo cercando su Google le immagini del problema (anziché il testo). Il loro ingombrante rettangolo esterno è (per fortuna) facile da rimuovere.
Nota che dovrai ridefinire il comportamento del pulsante (poiché hai cambiato ControlTemplate). Cioè, sarà necessario definire il comportamento del pulsante quando si fa clic utilizzando un tag Trigger (Proprietà = & Quot; IsPressed & Quot; Valore = & Quot; true & Quot;) in ControlTemplate.Triggers etichetta. Spero che questo salvi qualcun altro il tempo che ho perso :)