如何使圆angular边界的内容也是圆angular的?
我有一个包含3×3网格的圆angular边框元素。 网格的angular落突出了边界。 我该如何解决这个问题? 我尝试使用ClipToBounds,但没有得到任何地方。 谢谢你的帮助
这里是Jobi提到的这个线程的亮点
- 装饰者(即边框)或布局面板(即Stackpanel)都不具备这种行为。
- ClipToBounds用于布局。 ClipToBounds不会阻止一个元素超出其边界; 它只是防止儿童的布局“溢出”。 另外ClipToBounds = True对于大多数元素是不需要的,因为它们的实现不允许他们的内容的布局溢出。 最显着的例外是帆布。
- 最后,Border将圆angular视为其布局边界内的graphics。
这里是一个inheritance自Border的类的实现,并实现了正确的function:
/// <Remarks> /// As a side effect ClippingBorder will surpress any databinding or animation of /// its childs UIElement.Clip property until the child is removed from ClippingBorder /// </Remarks> 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:
<Border CornerRadius="30" Background="Green"> <Border.OpacityMask> <VisualBrush> <VisualBrush.Visual> <Border Background="Black" SnapsToDevicePixels="True" CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource AncestorType=Border}}" Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Border}}" Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Border}}" /> </VisualBrush.Visual> </VisualBrush> </Border.OpacityMask> <TextBlock Text="asdas das d asd a sd a sda" /> </Border>
更新:find一个更好的方法来实现相同的结果。 您现在也可以用任何其他元素replace边界 。
<Grid> <Grid.OpacityMask> <VisualBrush Visual="{Binding ElementName=Border1}" /> </Grid.OpacityMask> <Border x:Name="Border1" CornerRadius="30" Background="Green" /> <TextBlock Text="asdas das d asd a sd a sda" /> </Grid>
所以我只是遇到了这个解决scheme,然后跟随Jobi提供的msdn论坛链接,花了20分钟写我自己的ClippingBorder控制。
然后我意识到CornerRadius属性types不是双重的,而是System.Windows.CornerRaduis,它接受4个双打,每个angular落一个。
所以我现在要列出另一种替代解决scheme,这将最有可能满足将来偶然遇到这个post的大多数人的要求…
假设你有这样的XAML:
<Border CornerRadius="10"> <Grid> ... your UI ... </Grid> </Border>
问题是Grid元素的背景会stream过并显示圆angular。 确保您的<Grid>
具有透明背景,而不是将相同的画笔分配给<Border>
元素的“Background”属性。 没有更多的出血越过angular落,并不需要一大堆的CustomControl代码。
诚然,从理论上讲,客户区域仍然有可能超越angular落的边缘,但是您控制了内容,所以开发者应该能够拥有足够的填充,或者确保控件旁边的控件的形状边缘是合适的(在我的情况下,我的button是圆的,所以非常适合在angular落没有任何问题)。
正如Micah所提到的, ClipToBounds
不能用于Border.ConerRadius
。
有UIElement.Clip属性,这是Border
inheritance关系。
如果你知道边界的确切大小,那么这里是解决scheme:
<Border Background="Blue" CornerRadius="3" Height="100" Width="100"> <Border.Clip> <RectangleGeometry RadiusX="3" RadiusY="3" Rect="0,0,100,100"/> </Border.Clip> <Grid Background="Green"/> </Border>
如果大小未知或dynamic,则可以使用Converter
for Border.Clip
。 在这里看到解决scheme。
使用@安德鲁·米哈伊洛夫的解决scheme,你可以定义一个简单的类,这使得为每个受影响的元素定义一个VisualBrush
手动是不必要的:
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); } }
要testing这个,只需编译以下两个示例:
<!-- You should see a blue rectangle with rounded corners/no red! --> <Controls:ClippedBorder Background="Red" CornerRadius="10" Height="425" HorizontalAlignment="Center" VerticalAlignment="Center" Width="425"> <Border Background="Blue"> </Border> </Controls:ClippedBorder> <!-- You should see a blue rectangle with NO rounded corners/still no red! --> <Border Background="Red" CornerRadius="10" Height="425" HorizontalAlignment="Center" VerticalAlignment="Center" Width="425"> <Border Background="Blue"> </Border> </Border>
使网格更小或边框更大。 以便边界元素完全包含网格。
或者看看你是否可以使网格的背景透明,以便“伸出”不明显。
更新:糟糕,没有注意到这是一个WPF的问题。 我不熟悉这一点。 这是一般的HTML / CSSbuild议。 也许它有帮助…