Come rendere il contenuto di un bordo arrotondato con angoli arrotondati?

Ho un elemento di bordo con angoli arrotondati contenente una griglia 3×3. Gli angoli della griglia stanno fuoriuscendo dal confine. Come posso ripararlo? Ho provato a utilizzare ClipToBounds ma non ho ottenuto nulla. Grazie per l’aiuto

Ecco i punti salienti di questo thread menzionato da Jobi

  • Nessuno dei decoratori (es. Border) o dei pannelli di layout (es. Stackpanel) viene fornito con questo comportamento immediato.
  • ClipToBounds è per il layout. ClipToBounds non impedisce a un elemento di disegnare al di fuori dei suoi limiti; semplicemente impedisce ai layout dei bambini di “versare”. Inoltre ClipToBounds = True non è necessario per la maggior parte degli elementi perché le loro implementazioni non consentono comunque al loro contenuto di rovesciarsi. L’eccezione più notevole è Canvas.
  • Infine Border considera gli angoli arrotondati come disegni all’interno dei limiti del suo layout.

Ecco un’implementazione di una class che eredita da Border e implementa la funzionalità corretta:

///  /// As a side effect ClippingBorder will surpress any databinding or animation of /// its childs UIElement.Clip property until the child is removed from ClippingBorder ///  public class ClippingBorder : Border { protected override void OnRender(DrawingContext dc) { OnApplyChildClip(); base.OnRender(dc); } public override UIElement Child { get { return base.Child; } set { if (this.Child != value) { if(this.Child != null) { // Restore original clipping this.Child.SetValue(UIElement.ClipProperty, _oldClip); } if(value != null) { _oldClip = value.ReadLocalValue(UIElement.ClipProperty); } else { // If we dont set it to null we could leak a Geometry object _oldClip = null; } base.Child = value; } } } protected virtual void OnApplyChildClip() { UIElement child = this.Child; if(child != null) { _clipRect.RadiusX = _clipRect.RadiusY = Math.Max(0.0, this.CornerRadius.TopLeft - (this.BorderThickness.Left * 0.5)); _clipRect.Rect = new Rect(Child.RenderSize); child.Clip = _clipRect; } } private RectangleGeometry _clipRect = new RectangleGeometry(); private object _oldClip; } 

XAML puro:

           

Aggiornamento: trovato un modo migliore per ottenere lo stesso risultato. Puoi anche sostituire Border con qualsiasi altro elemento ora.

        

Esempio

Come Micah ha menzionato ClipToBounds non funzionerà con Border.ConerRadius .

Esiste la proprietà UIElement.Clip , che eredita il Border .

Se conosci la dimensione esatta del confine, ecco la soluzione:

       

Se la dimensione non è nota o dynamic, è ansible utilizzare Converter per Border.Clip . Vedi la soluzione qui .

Quindi ho appena trovato questa soluzione, poi ho seguito il link al forum msdn fornito da Jobi e ho trascorso 20 minuti a scrivere il mio controllo ClippingBorder.

Poi mi sono reso conto che il tipo di proprietà CornerRadius non è un doppio, ma System.Windows.CornerRaduis che accetta 4 doppi, uno per ogni angolo.

Quindi ho intenzione di elencare un’altra soluzione alternativa ora, che molto probabilmente soddisferà i requisiti della maggior parte delle persone che inciamperanno su questo post in futuro …

Supponiamo che tu abbia XAML che assomiglia a questo:

   ... your UI ...   

E il problema è che lo sfondo per l’elemento Grid scorre attraverso e mostra oltre gli angoli arrotondati. Assicurati che il tuo abbia uno sfondo trasparente invece di assegnare lo stesso pennello alla proprietà “Background” dell’elemento . Non più sanguinamento oltre gli angoli e nessuna necessità di un intero gruppo di codice CustomControl.

È vero che, in teoria, l’area client ha ancora il potenziale di disegnare oltre il bordo dell’angolo, ma tu controlli quel contenuto in modo che tu, come sviluppatore, sia in grado di avere abbastanza padding, o assicurati che la forma del controllo accanto al il bordo è appropriato (nel mio caso i miei pulsanti sono rotondi, quindi si adattano molto bene nell’angolo senza problemi).

Usando la soluzione di @Andrew Mikhailov, puoi definire una class semplice, che rende VisualBrush definizione di un VisualBrush per ciascun elemento interessato:

 public class ClippedBorder : Border { public ClippedBorder() : base() { var e = new Border() { Background = Brushes.Black, SnapsToDevicePixels = true, }; e.SetBinding(Border.CornerRadiusProperty, new Binding() { Mode = BindingMode.OneWay, Path = new PropertyPath("CornerRadius"), Source = this }); e.SetBinding(Border.HeightProperty, new Binding() { Mode = BindingMode.OneWay, Path = new PropertyPath("ActualHeight"), Source = this }); e.SetBinding(Border.WidthProperty, new Binding() { Mode = BindingMode.OneWay, Path = new PropertyPath("ActualWidth"), Source = this }); OpacityMask = new VisualBrush(e); } } 

Per testare questo, basta compilare i seguenti due esempi:

           

Rendi la griglia più piccola o allarga il bordo. In modo che l’elemento del bordo contenga completamente la griglia.

In alternativa, vedi se è ansible rendere trasparente lo sfondo della griglia, in modo che lo “spunta” non sia visibile.

Aggiornamento: Oops, non ho notato che si trattava di una domanda WPF. Non mi è familiare. Questo era un consiglio generale HTML / CSS. Forse aiuta …