.net मैं रिलेवेटसोर्स के साथ डब्ल्यूपीएफ बाइंडिंग का उपयोग कैसे करूं?



wpf xaml (12)

मैं WPF बाइंडिंग के साथ RelativeSource स्रोत का उपयोग कैसे करूं और विभिन्न उपयोग-मामले क्या हैं?


Answer #1

बेचिर बेजाउई ने यहां अपने लेख में डब्ल्यूपीएफ में संबंधित स्रोतों के उपयोग के मामलों का खुलासा किया:

सापेक्ष स्रोत एक मार्कअप एक्सटेंशन है जिसे विशेष रूप से बाध्यकारी मामलों में उपयोग किया जाता है जब हम ऑब्जेक्ट की किसी अन्य संपत्ति को किसी दिए गए ऑब्जेक्ट की किसी संपत्ति को बांधने का प्रयास करते हैं, जब हम ऑब्जेक्ट की किसी अन्य संपत्ति को अपने रिश्तेदार माता-पिता को बांधने का प्रयास करते हैं, कस्टम नियंत्रण विकास के मामले में अंततः एक्सएएमएल के एक टुकड़े पर एक निर्भरता संपत्ति मूल्य को बाध्य करते समय और अंत में बाध्य डेटा की एक श्रृंखला के अंतर का उपयोग करने के मामले में। उन सभी स्थितियों को सापेक्ष स्रोत मोड के रूप में व्यक्त किया जाता है। मैं उन सभी मामलों को एक-एक करके बेनकाब कर दूंगा।

  1. मोड स्व:

इस मामले की कल्पना करो, एक आयताकार जिसे हम चाहते हैं कि इसकी ऊंचाई हमेशा इसकी चौड़ाई के बराबर होती है, एक वर्ग चलो कहते हैं। हम तत्व नाम का उपयोग कर ऐसा कर सकते हैं

<Rectangle Fill="Red" Name="rectangle" 
                Height="100" Stroke="Black" 
                Canvas.Top="100" Canvas.Left="100"
                Width="{Binding ElementName=rectangle,
                Path=Height}"/>

लेकिन इस उपरोक्त मामले में हम बाध्यकारी वस्तु, अर्थात् आयताकार का नाम इंगित करने के लिए बाध्य हैं। हम सापेक्ष स्रोत का उपयोग करके अलग-अलग उद्देश्य तक पहुंच सकते हैं

<Rectangle Fill="Red" Height="100" 
               Stroke="Black" 
               Width="{Binding RelativeSource={RelativeSource Self},
               Path=Height}"/>

उस मामले के लिए हम बाध्यकारी वस्तु के नाम का उल्लेख करने के लिए बाध्य नहीं हैं और जब भी ऊंचाई बदल जाती है तो चौड़ाई हमेशा ऊँचाई के बराबर होगी।

यदि आप ऊंचाई के आधा होने के लिए चौड़ाई को पैरामीटर करना चाहते हैं तो आप बाध्यकारी मार्कअप एक्सटेंशन में कनवर्टर जोड़ कर ऐसा कर सकते हैं। आइए अब एक और मामला कल्पना करें:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
               Path=Parent.ActualWidth}"/>

उपरोक्त मामले का उपयोग किसी दिए गए तत्व की किसी दिए गए गुण को अपने प्रत्यक्ष माता-पिता को टाई करने के लिए किया जाता है क्योंकि इस तत्व में एक संपत्ति होती है जिसे अभिभावक कहा जाता है। यह हमें एक अन्य रिश्तेदार स्रोत मोड की ओर ले जाता है जो FindAncestor है।

  1. मोड FindAncestor

इस मामले में, किसी दिए गए तत्व की एक संपत्ति अपने माता-पिता, कोर के साथ बंधी जाएगी। उपरोक्त मामले के साथ मुख्य अंतर यह तथ्य है कि, संपत्ति को बांधने के लिए पदानुक्रम में पूर्वजों के प्रकार और पूर्वज पद को निर्धारित करने के लिए आप पर निर्भर है। वैसे XAML के इस टुकड़े के साथ खेलने की कोशिश करें

<Canvas Name="Parent0">
    <Border Name="Parent1"
             Width="{Binding RelativeSource={RelativeSource Self},
             Path=Parent.ActualWidth}"
             Height="{Binding RelativeSource={RelativeSource Self},
             Path=Parent.ActualHeight}">
        <Canvas Name="Parent2">
            <Border Name="Parent3"
            Width="{Binding RelativeSource={RelativeSource Self},
           Path=Parent.ActualWidth}"
           Height="{Binding RelativeSource={RelativeSource Self},
              Path=Parent.ActualHeight}">
               <Canvas Name="Parent4">
               <TextBlock FontSize="16" 
               Margin="5" Text="Display the name of the ancestor"/>
               <TextBlock FontSize="16" 
                 Margin="50" 
            Text="{Binding RelativeSource={RelativeSource  
                       FindAncestor,
                       AncestorType={x:Type Border}, 
                       AncestorLevel=2},Path=Name}" 
                       Width="200"/>
                </Canvas>
            </Border>
        </Canvas>
     </Border>
   </Canvas>

उपर्युक्त स्थिति दो टेक्स्टब्लॉक तत्वों की है जो सीमाओं और कैनवास तत्वों की एक श्रृंखला के भीतर एम्बेडेड हैं जो उनके पदानुक्रमित माता-पिता का प्रतिनिधित्व करते हैं। दूसरा टेक्स्टब्लॉक दिए गए माता-पिता का नाम सापेक्ष स्रोत स्तर पर प्रदर्शित करेगा।

तो पूर्वजों Level = 2 को पूर्वज Level = 1 में बदलने की कोशिश करें और देखें कि क्या होता है। फिर पूर्वजों के प्रकार को पूर्वजों के प्रकार = सीमा से पूर्वजों प्रकार = कैनवास में बदलने का प्रयास करें और देखें कि क्या होता है।

प्रदर्शित पाठ पूर्वजों के प्रकार और स्तर के अनुसार बदल जाएगा। तो क्या होता है यदि पूर्वजों का स्तर पूर्वजों के प्रकार के लिए उपयुक्त नहीं है? यह एक अच्छा सवाल है, मुझे पता है कि आप इसे पूछने वाले हैं। प्रतिक्रिया कोई फर्क नहीं पड़ता है और टेक्स्टबॉक स्तर पर नोटिंग प्रदर्शित किए जाएंगे।

  1. TemplatedParent

यह मोड नियंत्रण नियंत्रक प्रॉपर्टी को उस नियंत्रण की एक संपत्ति से जोड़ता है जो ControlTemplate पर लागू होता है। इस मुद्दे को अच्छी तरह से समझने के लिए यहां एक उदाहरण है

<Window.Resources>
<ControlTemplate x:Key="template">
        <Canvas>
            <Canvas.RenderTransform>
                <RotateTransform Angle="20"/>
                </Canvas.RenderTransform>
            <Ellipse Height="100" Width="150" 
                 Fill="{Binding 
            RelativeSource={RelativeSource TemplatedParent},
            Path=Background}">

              </Ellipse>
            <ContentPresenter Margin="35" 
                  Content="{Binding RelativeSource={RelativeSource  
                  TemplatedParent},Path=Content}"/>
        </Canvas>
    </ControlTemplate>
</Window.Resources>
    <Canvas Name="Parent0">
    <Button   Margin="50" 
              Template="{StaticResource template}" Height="0" 
              Canvas.Left="0" Canvas.Top="0" Width="0">
        <TextBlock FontSize="22">Click me</TextBlock>
    </Button>
 </Canvas>

अगर मैं किसी दिए गए नियंत्रण के गुणों को उसके नियंत्रण टेम्पलेट पर लागू करना चाहता हूं तो मैं टेम्पलेटेड पैरा मोड का उपयोग कर सकता हूं। इस मार्कअप एक्सटेंशन में भी ऐसा ही एक है जो टेम्पलेट बाइंडिंग है जो पहले के एक छोटे से हाथ का एक छोटा सा हाथ है, लेकिन टेम्पलेट बाइंडिंग का परीक्षण टेम्पलेटेड पेरेंट के विपरीत संकलन समय पर किया जाता है जिसका मूल्यांकन पहले रन के बाद किया जाता है। जैसा कि आप बोले आंकड़े में टिप्पणी कर सकते हैं, पृष्ठभूमि और सामग्री बटन के भीतर से नियंत्रण टेम्पलेट पर लागू होती है।


Answer #2

मैंने WPF के बाध्यकारी वाक्यविन्यास को सरल बनाने के लिए एक लाइब्रेरी बनाई है जिसमें सापेक्ष स्रोत का उपयोग करना आसान हो गया है। यहाँ कुछ उदाहरण हैं। पहले:

{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}
{Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}
{Binding Path=Text, ElementName=MyTextBox}

बाद:

{BindTo PathToProperty}
{BindTo Ancestor.typeOfAncestor.PathToProperty}
{BindTo Template.PathToProperty}
{BindTo #MyTextBox.Text}

यहां एक उदाहरण दिया गया है कि विधि बाध्यकारी कैसे सरल है। पहले:

// C# code
private ICommand _saveCommand;
public ICommand SaveCommand {
 get {
  if (_saveCommand == null) {
   _saveCommand = new RelayCommand(x => this.SaveObject());
  }
  return _saveCommand;
 }
}

private void SaveObject() {
 // do something
}

// XAML
{Binding Path=SaveCommand}

बाद:

// C# code
private void SaveObject() {
 // do something
}

// XAML
{BindTo SaveObject()}

आप यहां लाइब्रेरी पा सकते हैं: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html

'BEFORE' उदाहरण में नोट करें कि मैं विधि बाध्यकारी के लिए उपयोग करता हूं कि कोड पहले से ही RelayCommand का उपयोग करके अनुकूलित किया गया था, जिसे मैंने पिछली बार चेक किया था, वह WPF का मूल भाग नहीं है। इसके बिना 'पहले' उदाहरण भी लंबा होता।


Answer #3

इस मामले की कल्पना करो, एक आयताकार जिसे हम चाहते हैं कि इसकी ऊंचाई हमेशा इसकी चौड़ाई के बराबर होती है, एक वर्ग चलो कहते हैं। हम तत्व नाम का उपयोग कर ऐसा कर सकते हैं

<Rectangle Fill="Red" Name="rectangle" 
                    Height="100" Stroke="Black" 
                    Canvas.Top="100" Canvas.Left="100"
                    Width="{Binding ElementName=rectangle,
                    Path=Height}"/>

लेकिन इस उपरोक्त मामले में हम बाध्यकारी वस्तु, अर्थात् आयताकार का नाम इंगित करने के लिए बाध्य हैं। हम सापेक्ष स्रोत का उपयोग करके अलग-अलग उद्देश्य तक पहुंच सकते हैं

<Rectangle Fill="Red" Height="100" 
                   Stroke="Black" 
                   Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Height}"/>

उस मामले के लिए हम बाध्यकारी वस्तु के नाम का उल्लेख करने के लिए बाध्य नहीं हैं और जब भी ऊंचाई बदल जाती है तो चौड़ाई हमेशा ऊँचाई के बराबर होगी।

यदि आप ऊंचाई के आधा होने के लिए चौड़ाई को पैरामीटर करना चाहते हैं तो आप बाध्यकारी मार्कअप एक्सटेंशन में कनवर्टर जोड़ कर ऐसा कर सकते हैं। आइए अब एक और मामला कल्पना करें:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Parent.ActualWidth}"/>

उपरोक्त मामले का उपयोग किसी दिए गए तत्व की किसी दिए गए गुण को अपने प्रत्यक्ष माता-पिता को टाई करने के लिए किया जाता है क्योंकि इस तत्व में एक संपत्ति होती है जिसे अभिभावक कहा जाता है। यह हमें एक अन्य रिश्तेदार स्रोत मोड की ओर ले जाता है जो FindAncestor है।


Answer #4

चूंकि यह इस समस्या के लिए Google का शीर्ष है, मैंने सोचा कि मैं कुछ उपयोगी बिट्स और टुकड़े करूंगा:
यहां कोड में इसे अधिकतर करने का तरीका बताया गया है:

Binding b = new Binding();
b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, this.GetType(), 1);
b.Path = new PropertyPath("MyElementThatNeedsBinding");
MyLabel.SetBinding(ContentProperty, b);

मैंने इसे बड़े पैमाने पर कॉपी किया: http://social.msdn.microsoft.com/Forums/en/wpf/thread/c5a59f07-c932-4715-8774-fa7e8472b75b

साथ ही, एमएसडीएन पेज बहुत अच्छे हैं जहां तक ​​उदाहरण जाते हैं: http://msdn.microsoft.com/en-us/library/system.windows.data.relativesource.aspx


Answer #5

यह ध्यान देने योग्य है कि उन लोगों के लिए जो सिल्वरलाइट की इस सोच में ठोकर खा रहे हैं:

सिल्वरलाइट इन आदेशों में से केवल एक कम सबसेट प्रदान करता है


Answer #6
Binding RelativeSource={
    RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemType}
}
...

RelativeSource की डिफ़ॉल्ट विशेषता Mode प्रॉपर्टी है। वैध मानों का एक पूरा सेट यहां दिया गया है ( एमएसडीएन से ):

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

  • TemplatedParent उस तत्व को संदर्भित करता है जिस पर टेम्पलेट (जिसमें डेटा-बाध्य तत्व मौजूद है) लागू होता है। यह टेम्पलेट बाइंडिंग एक्सटेंशन सेट करने के समान है और केवल तभी लागू होता है जब बाध्यकारी टेम्पलेट के भीतर हो।

  • स्वयं उस तत्व को संदर्भित करता है जिस पर आप बाध्यकारी सेट कर रहे हैं और आपको उस तत्व की एक संपत्ति को उसी तत्व पर किसी अन्य प्रॉपर्टी से बांधने की अनुमति देता है।

  • FindAncestor डेटा-बाध्य तत्व की मूल श्रृंखला में पूर्वजों को संदर्भित करता है। आप इसका उपयोग किसी विशिष्ट प्रकार या उसके उप-वर्ग के पूर्वजों से जुड़ने के लिए कर सकते हैं। यदि आप पूर्वजों टाइप और / या पूर्वज लेवल को निर्दिष्ट करना चाहते हैं तो यह वह मोड है जिसका आप उपयोग करते हैं।


Answer #7

मैंने हर जवाब नहीं पढ़ा लेकिन मैं सिर्फ एक बटन के सापेक्ष स्रोत कमांड बाइंडिंग के मामले में यह जानकारी जोड़ना चाहता हूं। जब आप Mode=FindAncestor साथ सापेक्ष स्रोत का उपयोग करते हैं, तो बाध्यकारी इस प्रकार होना चाहिए:

Command="{Binding Path=DataContext.CommandProperty, RelativeSource={...}}"

यदि आप अपने पथ में डेटाकॉन्टेक्स्ट नहीं जोड़ते हैं, निष्पादन समय पर वह संपत्ति को पुनर्प्राप्त नहीं कर सकता है।


Answer #8

टेम्पलेटेड माता-पिता को मत भूलना:

<Binding RelativeSource="{RelativeSource TemplatedParent}"/>

या

{Binding RelativeSource={RelativeSource TemplatedParent}}

Answer #9

मैंने सिल्वरलाइट में एक मूल तत्व के डेटाकॉन्टेक्स्ट तक पहुंचने के लिए एक और समाधान पोस्ट किया है जो मेरे लिए काम करता है। यह Binding ElementName का उपयोग करता है।


Answer #10

यह इस पैटर्न के उपयोग का एक उदाहरण है जो खाली डेटाग्रिड्स पर मेरे लिए काम करता है।

<Style.Triggers>
    <DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
        <Setter Property="Background">
            <Setter.Value>
                <VisualBrush Stretch="None">
                    <VisualBrush.Visual>
                        <TextBlock Text="We did't find any matching records for your search..." FontSize="16" FontWeight="SemiBold" Foreground="LightCoral"/>
                    </VisualBrush.Visual>
                </VisualBrush>
            </Setter.Value>
        </Setter>
    </DataTrigger>
</Style.Triggers>

Answer #11

एमवीवीएम आर्किटेक्चर के संदर्भ में यहां एक और दृश्य स्पष्टीकरण दिया गया है:


Answer #12

यदि आप वस्तु पर किसी अन्य संपत्ति से जुड़ना चाहते हैं:

{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}

यदि आप पूर्वजों पर संपत्ति प्राप्त करना चाहते हैं:

{Binding Path=PathToProperty,
    RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}

यदि आप टेम्पलेट पैरेंट पर एक संपत्ति प्राप्त करना चाहते हैं (तो आप ControlTemplate में 2 तरीके बाइंडिंग कर सकते हैं)

{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}

या, छोटा (यह केवल वनवे बाइंडिंग के लिए काम करता है):

{TemplateBinding Path=PathToProperty}




relativesource