Nous sommes en train de créer une application XBAP dans laquelle nous avons besoin d'avoir des coins arrondis à différents endroits dans une seule page et nous aimerions avoir un conteneur WPF Rounded Corner pour y placer un tas d'autres éléments. Quelqu'un a-t-il des suggestions ou des exemples de code sur la meilleure façon de réaliser ceci ? Soit avec des styles sur un ou en créant un contrôle personnalisé ?
Réponses
Trop de publicités?Je sais que ce n'est pas une réponse à la question initiale ... mais vous voulez souvent découper le contenu intérieur de la bordure à coins arrondis que vous venez de créer.
Chris Cavanagh est venu avec une excellent moyen pour faire cela.
J'ai essayé plusieurs approches différentes à ce sujet... 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>
J'ai dû le faire moi-même, alors j'ai pensé poster une autre réponse ici.
Voici une autre façon de créer une bordure d'angle arrondi et clipsez son contenu interne . C'est le moyen le plus simple d'utiliser 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 du 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();
}
}
Mise en œuvre en code VB.Net de la solution de contrôle des frontières de kobusb. Je l'ai utilisé pour remplir une ListBox de contrôles de boutons. Les contrôles de boutons sont créés à partir d'extensions MEF. Chaque extension utilise l'attribut ExportMetaData du MEF pour une description de l'extension. Les extensions sont des objets graphiques VisiFire. L'utilisateur appuie sur un bouton, sélectionné dans la liste de 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 en forme de rectangle arrondi, vous devriez consulter le document suivant L'exemple de msdn . Je l'ai trouvé en cherchant sur Google des images du problème (au lieu du texte). Leur rectangle extérieur encombrant est (heureusement) facile à enlever.
Notez que vous devrez redéfinir le comportement du bouton (puisque vous avez modifié le ControlTemplate). En d'autres termes, vous devrez définir le comportement du bouton lorsqu'il est cliqué en utilisant une balise Trigger (Property="IsPressed" Value="true") dans la balise ControlTemplate.Triggers. J'espère que cela fera gagner à quelqu'un d'autre le temps que j'ai perdu :)