2008-11-27 13 views
39

मेरे पास एक 3x3 ग्रिड युक्त गोलाकार कोनों वाले सीमा तत्व हैं। ग्रिड के कोनों सीमा से बाहर चिपके हुए हैं। मैं कैसे इसे ठीक कर सकता हूं? मैंने क्लिपटोबाउंड्स का उपयोग करने की कोशिश की लेकिन कहीं भी नहीं मिला। आपकी मदद के लिए धन्यवादएक गोल-कोने वाली सीमा की सामग्री को कैसे गोल किया जाना चाहिए?

उत्तर

47

यहाँ से सज्जाकार की Jobi

  • कोई नहीं (यानी सीमा) या लेआउट पैनलों (यानी StackPanel) का उल्लेख इस thread का मुख्य आकर्षण हैं इस व्यवहार के बाहर के साथ आते हैं -डिब्बा।
  • क्लिपटॉबाउंड लेआउट के लिए है। ClipToBounds किसी तत्व को इसकी सीमाओं से बाहर खींचने से नहीं रोकता है; यह सिर्फ 'स्पिलिंग' से बच्चों के लेआउट को रोकता है। इसके अतिरिक्त ClipToBounds = अधिकांश तत्वों के लिए सत्य की आवश्यकता नहीं है क्योंकि उनके कार्यान्वयन उनकी सामग्री के लेआउट को किसी भी तरह फैलाने की अनुमति नहीं देते हैं। सबसे उल्लेखनीय अपवाद कैनवास है।
  • अंत में सीमा गोलाकार कोनों को अपने लेआउट की सीमाओं के अंदर चित्रों के रूप में मानती है।

यहां कक्षा कि सीमा से विरासत के एक कार्यान्वयन है और उचित रूप से लागू करता है:

 /// <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; 
    } 
+0

यह समाधान यहां एक नई कक्षा बनाने के बजाय कनवर्टर का उपयोग करता है: http://stackoverflow.com/questions/5649875/how-to-make-the-border-trim-the-child-elements नोट: मुझे घोंसला घूमना पड़ा मेरी रंगीन सीमा को बनाए रखने के लिए ऑब्जेक्ट्स (पृष्ठभूमि बिना घोंसले के ठीक काम करती है) –

+0

क्या आप कृपया अपने कोड में तर्क की व्याख्या कर सकते हैं? मुझे '_oldClip' के उद्देश्य को समझने की प्रतीत नहीं हो रही है और आप इसे 'रेडियसएक्स' और 'त्रिज्या' क्यों चुन रहे हैं। कॉर्नर रेडियस। टोपीलेफ्ट - (यह। सीमाचित्रता। लिफ्ट * 0.5)'। –

0

ग्रिड को छोटा या सीमा बड़ा बनाएं। ताकि सीमा तत्व पूरी तरह से ग्रिड शामिल हो।

वैकल्पिक रूप से देखें कि क्या आप ग्रिड की पृष्ठभूमि पारदर्शी बना सकते हैं, ताकि "चिपकने वाला" ध्यान देने योग्य न हो।

अद्यतन: ओह, यह नहीं देखा कि यह एक WPF प्रश्न था। मैं उससे परिचित नहीं हूँ। यह सामान्य एचटीएमएल/सीएसएस सलाह थी। शायद यह मदद करता है ...

+0

लेकिन आप सही हैं कि एक तार्किक उत्तर, और यह WPF में कई स्थितियों में भी काम करता है। –

7

तो मैं सिर्फ इस समाधान में आए, तो MSDN मंच लिंक में पीछा किया कि Jobi प्रदान की है और खर्च 20 अपने स्वयं के ClippingBorder नियंत्रण लिखने के मिनट।

तब मुझे एहसास हुआ कि कॉर्नर रेडियस संपत्ति का प्रकार एक डबल नहीं है, लेकिन System.Windows.CornerRaduis जो प्रत्येक कोने के लिए 4 युगल स्वीकार करता है।

तो मैं अब एक और वैकल्पिक समाधान की सूची जा रहा हूँ, जो सबसे अधिक संभावना है कि ज्यादातर लोगों को जो भविष्य में इस पोस्ट पर ठोकर होगा की आवश्यकताओं को पूरा करेगा ...

मान लीजिए कि आप XAML जो की तरह लग रहा है चलो यह:

<Border CornerRadius="10"> 
    <Grid> 
     ... your UI ... 
    </Grid> 
</Border> 

और समस्या यह है कि ग्रिड तत्व के लिए पृष्ठभूमि गोलाकार कोनों से गुजरती है और दिखाती है। सुनिश्चित करें कि में <Border> तत्व की "पृष्ठभूमि" संपत्ति को उसी ब्रश को निर्दिष्ट करने के बजाय पारदर्शी पृष्ठभूमि है। कोनों के पीछे और खून बह रहा है और कस्टमकंट्रोल कोड के पूरे समूह की आवश्यकता नहीं है।

यह सच है कि सिद्धांत में, ग्राहक क्षेत्र में अभी भी कोने के किनारे के पीछे ड्राइंग की क्षमता है, लेकिन आप उस सामग्री को नियंत्रित करते हैं ताकि आप डेवलपर को पर्याप्त पैडिंग प्राप्त कर सकें, या सुनिश्चित करें कि आकार किनारे के बगल में नियंत्रण उपयुक्त है (मेरे मामले में, मेरे बटन गोल हैं, इसलिए किसी भी समस्या के बिना कोने में बहुत अच्छी तरह से फिट)।

6

जैसा कि मीका ने ClipToBounds का उल्लेख किया है Border.ConerRadius के साथ काम नहीं करेगा।

UIElement.Clip संपत्ति है, जो Border विरासत है।

<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> 

आकार ज्ञात नहीं है या गतिशील तो Border.Clip के लिए Converter इस्तेमाल किया जा सकता:

आप सीमा के सटीक आकार को जानते हैं, तो यहाँ समाधान है। समाधान here देखें।

34

शुद्ध 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> 

अद्यतन: एक ही परिणाम प्राप्त करने के लिए एक बेहतर तरीका मिले। आप अब सीमा को किसी अन्य तत्व के साथ प्रतिस्थापित भी कर सकते हैं।

<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> 

Example

+1

पहले उदाहरण में गोलाकार कोनों के पीछे कलाकृतियों से छुटकारा पाने के लिए (उदाहरण के लिए स्नूप टूल के साथ आप इसे बड़ा करते समय देख सकते हैं) आपको सीमा सीमा (उसी तरह) को बांधना होगा और बॉर्डरब्रश को व्हाइट पर सेट करना होगा। यह सीमा की सीमा को काट देगा। –

+0

पहला उदाहरण अधिक सामान्य है क्योंकि यह पारदर्शी हो सकता है (क्लिपिंग आकार को इसकी पृष्ठभूमि के साथ दिखाई नहीं देना चाहिए)। –

1

@Andrew Mikhailov के समाधान का उपयोग करके आप एक साधारण वर्ग है, जो प्रत्येक प्रभावित तत्व मैन्युअल अनावश्यक के लिए एक 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); 
    } 
} 

यह परीक्षण करने के लिए, बस संकलन निम्नलिखित दो नमूने:

<!-- 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> 
संबंधित मुद्दे