Nous sommes en train de créer une application XBAP dont les coins arrondis doivent être arrondis à différents endroits sur une seule page et nous aimerions disposer d’un conteneur WPF Rounded Corner pour y placer un tas d’autres éléments. Quelqu'un at-il des suggestions ou un exemple de code sur la meilleure façon d’y parvenir? Avec des styles sur ou avec la création d'un contrôle personnalisé?
Vous n'avez pas besoin d'un contrôle personnalisé, il suffit de placer votre conteneur dans un élément border:
<Border BorderBrush="#FF000000" BorderThickness="1" CornerRadius="8">
<Grid/>
</Border>
Vous pouvez remplacer le <Grid/>
avec l'un des conteneurs de mise en page ...
Je sais que ce n'est pas une réponse à la question initiale ... mais vous voulez souvent couper le contenu intérieur de la bordure d'angle arrondi que vous venez de créer.
Chris Cavanagh a mis au point un excellente façon de faire exactement cela.
J'ai essayé plusieurs approches différentes à cet égard ... et je pense que celle-ci est géniale.
Voici le xaml ci-dessous:
<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>
Je devais le faire moi-même, alors j'ai pensé poster une autre réponse ici.
Voici un autre moyen de créer une bordure d’angle arrondie et de découper son contenu interne. C'est la méthode la plus simple en utilisant la propriété Clip. C'est bien si vous voulez éviter un VisualBrush.
Le 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>
Le code pour le convertisseur:
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();
}
}
Implémentation basée sur le code VB.Net de la solution de contrôle des frontières de kobusb. Je l'ai utilisé pour remplir un ListBox de contrôles Button. Les contrôles Button sont créés à partir d'extensions MEF. Chaque extension utilise l'attribut ExportMetaData de MEF pour une description de l'extension. Les extensions sont des objets de cartographie VisiFire. L'utilisateur appuie sur un bouton, sélectionné dans la liste des boutons, pour exécuter le graphique souhaité.
' 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
Si vous essayez de placer un bouton dans une bordure rectangulaire arrondie, vous devriez vérifier exemple de msdn . J'ai trouvé cela en recherchant des images du problème sur Google (au lieu de texte). Leur rectangle extérieur volumineux est (heureusement) facile à enlever.
Notez que vous devrez redéfinir le comportement du bouton (depuis que vous avez modifié le ControlTemplate). En d'autres termes, vous devez définir le comportement du bouton lorsque vous cliquez dessus à l'aide d'une balise Trigger (Property = "IsPressed" Value = "true") dans la balise ControlTemplate.Triggers. J'espère que cela épargnera à quelqu'un d'autre le temps que j'ai perdu :)