मैं नाम या प्रकार से WPF नियंत्रण कैसे पा सकता हूं?


264

मुझे दिए गए नाम या प्रकार से मेल खाने वाले नियंत्रणों के लिए WPF नियंत्रण पदानुक्रम खोजना होगा। मैं यह कैसे कर सकता हूँ?

जवाबों:


311

मैंने जॉन माइजेक और ट्राई क्यू के एल्गोरिदम द्वारा उपयोग किए जाने वाले टेम्पलेट प्रारूप को संयुक्त रूप से ऊपर एक खोजक एल्गोरिदम बनाने के लिए किया है जो किसी भी माता-पिता पर उपयोग किया जा सकता है। ध्यान रखें कि एक पेड़ को नीचे की ओर फिर से खोजना एक लंबी प्रक्रिया हो सकती है। मैंने केवल एक WPF एप्लिकेशन पर इसे स्पॉट-चेक किया है, कृपया किसी भी त्रुटि पर टिप्पणी करें जो आपको मिल सकती है और मैं अपना कोड सही करूंगा।

WPF स्नूप विज़ुअल ट्री को देखने में एक उपयोगी उपकरण है - मैं आपके काम की जाँच करने के लिए इस एल्गोरिथम का परीक्षण करते समय या इसका उपयोग करने की दृढ़ता से सलाह देता हूँ।

Tri Q के एल्गोरिथम में एक छोटी सी त्रुटि है। बच्चे के पाए जाने के बाद, यदि बच्चे> 1 है और हम फिर से पुनरावृति करते हैं तो हम ठीक से पाए गए बच्चे को अधिलेखित कर सकते हैं। इसलिए मैंने if (foundChild != null) break;इस स्थिति से निपटने के लिए अपने कोड में जोड़ा ।

/// <summary>
/// Finds a Child of a given item in the visual tree. 
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter. 
/// If not matching item can be found, 
/// a null parent is being returned.</returns>
public static T FindChild<T>(DependencyObject parent, string childName)
   where T : DependencyObject
{    
  // Confirm parent and childName are valid. 
  if (parent == null) return null;

  T foundChild = null;

  int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
  for (int i = 0; i < childrenCount; i++)
  {
    var child = VisualTreeHelper.GetChild(parent, i);
    // If the child is not of the request child type child
    T childType = child as T;
    if (childType == null)
    {
      // recursively drill down the tree
      foundChild = FindChild<T>(child, childName);

      // If the child is found, break so we do not overwrite the found child. 
      if (foundChild != null) break;
    }
    else if (!string.IsNullOrEmpty(childName))
    {
      var frameworkElement = child as FrameworkElement;
      // If the child's name is set for search
      if (frameworkElement != null && frameworkElement.Name == childName)
      {
        // if the child's name is of the request name
        foundChild = (T)child;
        break;
      }
    }
    else
    {
      // child element found.
      foundChild = (T)child;
      break;
    }
  }

  return foundChild;
}

इसे इस तरह से कॉल करें:

TextBox foundTextBox = 
   UIHelper.FindChild<TextBox>(Application.Current.MainWindow, "myTextBoxName");

नोट Application.Current.MainWindowकोई भी मूल विंडो हो सकती है।


@CrimsonX: हो सकता है कि मैं यह गलत कर रहा हूं ... मुझे एक समान आवश्यकता थी कि मुझे कंटेंटकंट्रोल (एक्सपैंडर) के अंदर एक कंट्रोल (लिस्टबॉक्स) प्राप्त करने की आवश्यकता थी। उपरोक्त कोड मेरे लिए काम नहीं कर रहा है .. जैसा कि एक पत्ती नोड (GetChildrenCount => 0) एक ContentControl है यह देखने के लिए मुझे उपरोक्त कोड को अपडेट करना पड़ा। यदि हाँ, जाँच करें कि क्या सामग्री नाम + प्रकार के मानदंड से मेल खाती है।
गिशु

@ गिशु - मुझे लगता है कि इस उद्देश्य के लिए काम करना चाहिए। क्या आप कॉल का उपयोग करने के तरीके के लिए अपना कोड कॉपी और पेस्ट कर सकते हैं? मुझे उम्मीद है कि यह FindChild <ListBox> (myExpanderName का विस्तार करें, "myListBoxName") होना चाहिए।
क्रिमसनएक्स

3
@CrimsonX मुझे लगता है कि मुझे एक और कोने का मामला मिला। मैं RibbonApplicationMenuItem में PART_SubmenuPlaceholder खोजने की कोशिश कर रहा था, लेकिन ऊपर कोड काम नहीं कर रहा था। इसे हल करने के लिए, मुझे निम्नलिखित को जोड़ने की जरूरत है: अगर (नाम == एलिमेंटनेम) बाकी {फाउंडचिल्ड = फाइंड चिल्ड (बच्चा, नाम) अगर (फाउंडल्ड! = अशक्त) टूट जाता है; }
केविन्दुब

6
कृपया सावधान रहें, उत्तर में एक बग या अधिक है। जैसे ही यह खोज प्रकार के एक बच्चे तक पहुंच जाएगा, यह बंद हो जाएगा। मुझे लगता है कि आपको अन्य उत्तरों पर विचार / प्राथमिकता देनी चाहिए।
एरिक ओउलेट

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

131

आप FrameworkElement.FindName (स्ट्रिंग) का उपयोग करके नाम से एक तत्व भी पा सकते हैं ।

दिया हुआ:

<UserControl ...>
    <TextBlock x:Name="myTextBlock" />
</UserControl>

कोड-बैक फ़ाइल में, आप लिख सकते हैं:

var myTextBlock = (TextBlock)this.FindName("myTextBlock");

बेशक, क्योंकि यह एक्स का उपयोग करके परिभाषित किया गया है: नाम, आप केवल उत्पन्न फ़ील्ड का संदर्भ दे सकते हैं, लेकिन शायद आप इसे सांख्यिकीय रूप से नहीं बल्कि गतिशील रूप से देखना चाहते हैं।

यह दृष्टिकोण टेम्प्लेट के लिए भी उपलब्ध है, जिसमें नामित आइटम कई बार (टेम्पलेट के उपयोग के बाद) दिखाई देता है।


6
इसके लिए आपको आवश्यक रूप से नाम विशेषता के लिए "x:" जोड़ना होगा।
ब्रायन बक

3
यह काम हमेशा नहीं लगता है। मेरे पास UserControls हैं जो प्रोग्राम के रूप में नेस्टेड ग्रिड में प्रॉपर्टीज विंडो की सामग्री के रूप में संयुक्त हैं। क्रिमसनएक्स का जवाब हालांकि ठीक काम करता है।
मैट

4
यह ItemControls भीतर तत्वों, listboxes, आदि के लिए काम नहीं करेगा
सोरेनसेन

67

आप नियंत्रण खोजने के लिए VisualTreeHelper का उपयोग कर सकते हैं । नीचे एक विधि है जो किसी विशिष्ट प्रकार के मूल नियंत्रण को खोजने के लिए VisualTreeHelper का उपयोग करता है। आप VisualTreeHelper का उपयोग अन्य तरीकों से नियंत्रण खोजने के लिए भी कर सकते हैं।

public static class UIHelper
{
   /// <summary>
   /// Finds a parent of a given item on the visual tree.
   /// </summary>
   /// <typeparam name="T">The type of the queried item.</typeparam>
   /// <param name="child">A direct or indirect child of the queried item.</param>
   /// <returns>The first parent item that matches the submitted type parameter. 
   /// If not matching item can be found, a null reference is being returned.</returns>
   public static T FindVisualParent<T>(DependencyObject child)
     where T : DependencyObject
   {
      // get parent item
      DependencyObject parentObject = VisualTreeHelper.GetParent(child);

      // we’ve reached the end of the tree
      if (parentObject == null) return null;

      // check if the parent matches the type we’re looking for
      T parent = parentObject as T;
      if (parent != null)
      {
         return parent;
      }
      else
      {
         // use recursion to proceed with next level
         return FindVisualParent<T>(parentObject);
      }
   }
}

इसे इस तरह से कॉल करें:

Window owner = UIHelper.FindVisualParent<Window>(myControl);

आप कैसे प्राप्त करते हैं या myControl क्या है?
Demodave

21

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

public static class UIChildFinder
{
    public static DependencyObject FindChild(this DependencyObject reference, string childName, Type childType)
    {
        DependencyObject foundChild = null;
        if (reference != null)
        {
            int childrenCount = VisualTreeHelper.GetChildrenCount(reference);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(reference, i);
                // If the child is not of the request child type child
                if (child.GetType() != childType)
                {
                    // recursively drill down the tree
                    foundChild = FindChild(child, childName, childType);
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = child;
                        break;
                    }
                }
                else
                {
                    // child element found.
                    foundChild = child;
                    break;
                }
            }
        }
        return foundChild;
    }
}

उम्मीद है यह आपको उपयोगी होगा।


2
ऊपर मेरे पोस्ट के अनुसार, आपके कोड में एक छोटी कार्यान्वयन त्रुटि है: stackoverflow.com/questions/636383/wpf-ways-to-find-controls/…
क्रिमसनएक्स

18

कोड के लिए मेरे एक्सटेंशन।

  • प्रकार के अनुसार एक बच्चे को खोजने के लिए अधिभार, प्रकार और मापदंड (विधेय) द्वारा, प्रकार के सभी बच्चों को खोजें जो मानदंडों को पूरा करते हैं
  • FindChildren विधि DependencyObject के लिए एक विस्तार विधि होने के अलावा एक पुनरावृत्ति है
  • FindChildren तार्किक उप-पेड़ भी चलता है। ब्लॉग पोस्ट में देखें जोश स्मिथ की पोस्ट।

स्रोत: https://code.google.com/p/gishu-util/source/browse/#git%2FWPF%2FU क्षमताएं

व्याख्यात्मक ब्लॉग पोस्ट: http://madcoderspeak.blogspot.com/2010/04/wpf-find-child-control-of-specific-type.html


-1 वास्तव में मैं क्या लागू करने वाला था (विधेय, पुनरावृत्ति, और विस्तार विधि), लेकिन स्रोत लिंक पर 404 है। यदि कोड को यहां शामिल किया गया है, तो +1 बदल जाएगा या स्रोत लिंक तय हो गया है!
cod3monk3y

@ cod3monk3y - Git माइग्रेशन ने लिंक को मार दिया लगता है :) यहां आप जाते हैं .. code.google.com/p/gishu-util/source/browse/…
Gishu

18

यदि आप एक विशिष्ट प्रकार के सभी नियंत्रणों को ढूंढना चाहते हैं, तो आप इस स्निपेट में भी दिलचस्पी ले सकते हैं

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject parent) 
        where T : DependencyObject
    {
        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);

            var childType = child as T;
            if (childType != null)
            {
                yield return (T)child;
            }

            foreach (var other in FindVisualChildren<T>(child))
            {
                yield return other;
            }
        }
    }

3
एक अच्छा लेकिन सुनिश्चित करें कि नियंत्रण लोड हो गया है अन्यथा GetChildrenCount वापस आ जाएगा 0.
क्लॉस Nji

@UrbanEsc, आप childदूसरी बार क्यों कास्ट करते हैं ? यदि आपके पास childTypeटाइप है T, तो आप अंदर लिख सकते हैं if: yield return childType... नहीं?
मैसिमिलियानो क्रूस

@MassimilianoKraus अरे, देर से प्रतिक्रिया के लिए खेद है, लेकिन आप सही हैं। मैं यह मेरे लिए विशेषता को फिर से लिखने कई बार झलकी, और इस प्रकार यह एक अलग जांच का एक टुकड़ा हो सकता है
UrbanEsc

16

यह कुछ तत्वों को खारिज कर देगा - आपको नियंत्रण की एक व्यापक सरणी का समर्थन करने के लिए इसे इस तरह विस्तारित करना चाहिए। एक संक्षिप्त चर्चा के लिए, एक नजर है यहाँ

 /// <summary>
 /// Helper methods for UI-related tasks.
 /// </summary>
 public static class UIHelper
 {
   /// <summary>
   /// Finds a parent of a given item on the visual tree.
   /// </summary>
   /// <typeparam name="T">The type of the queried item.</typeparam>
   /// <param name="child">A direct or indirect child of the
   /// queried item.</param>
   /// <returns>The first parent item that matches the submitted
   /// type parameter. If not matching item can be found, a null
   /// reference is being returned.</returns>
   public static T TryFindParent<T>(DependencyObject child)
     where T : DependencyObject
   {
     //get parent item
     DependencyObject parentObject = GetParentObject(child);

     //we've reached the end of the tree
     if (parentObject == null) return null;

     //check if the parent matches the type we're looking for
     T parent = parentObject as T;
     if (parent != null)
     {
       return parent;
     }
     else
     {
       //use recursion to proceed with next level
       return TryFindParent<T>(parentObject);
     }
   }

   /// <summary>
   /// This method is an alternative to WPF's
   /// <see cref="VisualTreeHelper.GetParent"/> method, which also
   /// supports content elements. Do note, that for content element,
   /// this method falls back to the logical tree of the element!
   /// </summary>
   /// <param name="child">The item to be processed.</param>
   /// <returns>The submitted item's parent, if available. Otherwise
   /// null.</returns>
   public static DependencyObject GetParentObject(DependencyObject child)
   {
     if (child == null) return null;
     ContentElement contentElement = child as ContentElement;

     if (contentElement != null)
     {
       DependencyObject parent = ContentOperations.GetParent(contentElement);
       if (parent != null) return parent;

       FrameworkContentElement fce = contentElement as FrameworkContentElement;
       return fce != null ? fce.Parent : null;
     }

     //if it's not a ContentElement, rely on VisualTreeHelper
     return VisualTreeHelper.GetParent(child);
   }
}

5
अधिवेशन से, मैं किसी भी Try*विधि को वापस करने की उम्मीद करूंगा boolऔर एक outपैरामीटर होगा जो प्रश्न में प्रकार लौटाता है, जैसे कि:bool IDictionary.TryGetValue(TKey key, out TValue value)
ड्रू नोक

@DrewNoakes क्या आप सुझाव है कि फिलिप इसे कहते हैं, तो? इसके अलावा, इस तरह की उम्मीद के साथ भी मुझे उसका कोड स्पष्ट और उपयोग करने के लिए स्पष्ट है।
सेविस

1
@ @Eves, इस मामले में मैं सिर्फ यह कहूंगा FindParent। मेरा यह नाम बताता है कि यह वापस आ सकता है nullTry*उपसर्ग तरह से मैं ऊपर का वर्णन में बीसीएल प्रयोग किया जाता है। यह भी ध्यान दें कि यहां अन्य अधिकांश उत्तर Find*नामकरण सम्मेलन का उपयोग करते हैं । यह केवल एक मामूली बात है, हालांकि :)
ड्रू नोक सेप

16

मैंने क्रिमसनएक्स का कोड संपादित किया क्योंकि यह सुपरक्लास प्रकारों के साथ काम नहीं कर रहा था:

public static T FindChild<T>(DependencyObject depObj, string childName)
   where T : DependencyObject
{
    // Confirm obj is valid. 
    if (depObj == null) return null;

    // success case
    if (depObj is T && ((FrameworkElement)depObj).Name == childName)
        return depObj as T;

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(depObj, i);

        //DFS
        T obj = FindChild<T>(child, childName);

        if (obj != null)
            return obj;
    }

    return null;
}

1
आप इस विधि का एक पार कर लेते हैं DependencyObjectकि नहीं है एक FrameworkElementयह एक अपवाद फेंक कर सकते हैं। इसके अलावा लूप के GetChildrenCountहर पुनरावृत्ति पर उपयोग करना forएक बुरा विचार लगता है।
टिम पोहलमैन

1
अच्छी तरह से, यह तो मैं भी नहीं जानता कि अगर यह अब और काम करता है 5 साल पहले से है, :)
andresp

मैंने सिर्फ इसका उल्लेख किया है, क्योंकि मैं इस पर ठोकर खाई थी और अन्य भी;)
टिम पोहलमैन ने

13

जब तक मुझे सामान्य रूप से पुनरावृत्ति पसंद है, यह C # में प्रोग्रामिंग करते समय पुनरावृत्ति के रूप में कुशल नहीं है, इसलिए शायद जॉन माइज़ेक द्वारा सुझाए गए समाधान की तुलना में निम्नलिखित समाधान शून्य है? यह किसी विशेष प्रकार के पूर्वज नियंत्रण को खोजने के लिए दिए गए नियंत्रण से पदानुक्रम की खोज करता है।

public static T FindVisualAncestorOfType<T>(this DependencyObject Elt)
    where T : DependencyObject
{
    for (DependencyObject parent = VisualTreeHelper.GetParent(Elt);
        parent != null; parent = VisualTreeHelper.GetParent(parent))
    {
        T result = parent as T;
        if (result != null)
            return result;
    }
    return null;
}

इसे इस तरह से कॉल करें Windowजिसमें एक नियंत्रण कहा जाता है ExampleTextBox:

Window window = ExampleTextBox.FindVisualAncestorOfType<Window>();

9

यहां यह नियंत्रित करने के लिए मेरा कोड टाइप द्वारा नियंत्रण पाया जाता है कि हम पदानुक्रम में कितने गहरे तक जाते हैं (maxDepth == 0 का अर्थ है असीम रूप से गहरा)।

public static class FrameworkElementExtension
{
    public static object[] FindControls(
        this FrameworkElement f, Type childType, int maxDepth)
    {
        return RecursiveFindControls(f, childType, 1, maxDepth);
    }

    private static object[] RecursiveFindControls(
        object o, Type childType, int depth, int maxDepth = 0)
    {
        List<object> list = new List<object>();
        var attrs = o.GetType()
            .GetCustomAttributes(typeof(ContentPropertyAttribute), true);
        if (attrs != null && attrs.Length > 0)
        {
            string childrenProperty = (attrs[0] as ContentPropertyAttribute).Name;
            foreach (var c in (IEnumerable)o.GetType()
                .GetProperty(childrenProperty).GetValue(o, null))
            {
                if (c.GetType().FullName == childType.FullName)
                    list.Add(c);
                if (maxDepth == 0 || depth < maxDepth)
                    list.AddRange(RecursiveFindControls(
                        c, childType, depth + 1, maxDepth));
            }
        }
        return list.ToArray();
    }
}

9

exciton80 ... मुझे आपके कोड को usercontrols के माध्यम से पुनरावृत्ति नहीं करने में समस्या हो रही थी। यह ग्रिड जड़ को मार रहा था और एक त्रुटि फेंक रहा था। मेरा मानना ​​है कि यह मेरे लिए इसे ठीक करता है:

public static object[] FindControls(this FrameworkElement f, Type childType, int maxDepth)
{
    return RecursiveFindControls(f, childType, 1, maxDepth);
}

private static object[] RecursiveFindControls(object o, Type childType, int depth, int maxDepth = 0)
{
    List<object> list = new List<object>();
    var attrs = o.GetType().GetCustomAttributes(typeof(ContentPropertyAttribute), true);
    if (attrs != null && attrs.Length > 0)
    {
        string childrenProperty = (attrs[0] as ContentPropertyAttribute).Name;
        if (String.Equals(childrenProperty, "Content") || String.Equals(childrenProperty, "Children"))
        {
            var collection = o.GetType().GetProperty(childrenProperty).GetValue(o, null);
            if (collection is System.Windows.Controls.UIElementCollection) // snelson 6/6/11
            {
                foreach (var c in (IEnumerable)collection)
                {
                    if (c.GetType().FullName == childType.FullName)
                        list.Add(c);
                    if (maxDepth == 0 || depth < maxDepth)
                        list.AddRange(RecursiveFindControls(
                            c, childType, depth + 1, maxDepth));
                }
            }
            else if (collection != null && collection.GetType().BaseType.Name == "Panel") // snelson 6/6/11; added because was skipping control (e.g., System.Windows.Controls.Grid)
            {
                if (maxDepth == 0 || depth < maxDepth)
                    list.AddRange(RecursiveFindControls(
                        collection, childType, depth + 1, maxDepth));
            }
        }
    }
    return list.ToArray();
}

8

मेरे पास इस तरह का एक अनुक्रम कार्य है (जो पूरी तरह से सामान्य है):

    public static IEnumerable<T> SelectAllRecursively<T>(this IEnumerable<T> items, Func<T, IEnumerable<T>> func)
    {
        return (items ?? Enumerable.Empty<T>()).SelectMany(o => new[] { o }.Concat(SelectAllRecursively(func(o), func)));
    }

तत्काल बच्चे प्राप्त करना:

    public static IEnumerable<DependencyObject> FindChildren(this DependencyObject obj)
    {
        return Enumerable.Range(0, VisualTreeHelper.GetChildrenCount(obj))
            .Select(i => VisualTreeHelper.GetChild(obj, i));
    }

पाखंडी पेड़ के नीचे सभी बच्चों को ढूंढना:

    public static IEnumerable<DependencyObject> FindAllChildren(this DependencyObject obj)
    {
        return obj.FindChildren().SelectAllRecursively(o => o.FindChildren());
    }

सभी नियंत्रण प्राप्त करने के लिए आप इसे विंडो पर कॉल कर सकते हैं।

आपके पास संग्रह होने के बाद, आप LINQ (यानी टाइप, कहां) का उपयोग कर सकते हैं।


6

चूंकि यह प्रश्न सामान्य है कि यह बहुत ही तुच्छ मामलों के जवाब की तलाश कर रहे लोगों को आकर्षित कर सकता है: यदि आप वंशज के बजाय सिर्फ एक बच्चा चाहते हैं, तो आप Linq का उपयोग कर सकते हैं:

private void ItemsControlItem_Loaded(object sender, RoutedEventArgs e)
{
    if (SomeCondition())
    {
        var children = (sender as Panel).Children;
        var child = (from Control child in children
                 where child.Name == "NameTextBox"
                 select child).First();
        child.Focus();
    }
}

या बेशक बच्चों पर लूप के लिए स्पष्ट है।


3

ये विकल्प पहले से ही C # में Visual Tree को ट्रेस करने के बारे में बात करते हैं। यह संभव है कि xaml में विज़ुअल ट्री के साथ-साथ RelativeSource मार्कअप एक्सटेंशन का उपयोग किया जाए। MSDN

प्रकार से खोजें

Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type <TypeToFind>}}}" 

2

यहाँ एक समाधान है जो एक लचीली विधेय का उपयोग करता है:

public static DependencyObject FindChild(DependencyObject parent, Func<DependencyObject, bool> predicate)
{
    if (parent == null) return null;

    int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < childrenCount; i++)
    {
        var child = VisualTreeHelper.GetChild(parent, i);

        if (predicate(child))
        {
            return child;
        }
        else
        {
            var foundChild = FindChild(child, predicate);
            if (foundChild != null)
                return foundChild;
        }
    }

    return null;
}

आप उदाहरण के लिए इसे इस तरह से कॉल कर सकते हैं:

var child = FindChild(parent, child =>
{
    var textBlock = child as TextBlock;
    if (textBlock != null && textBlock.Name == "MyTextBlock")
        return true;
    else
        return false;
}) as TextBlock;

1

यह कोड सिर्फ @CrimsonX उत्तर बग को ठीक करता है:

 public static T FindChild<T>(DependencyObject parent, string childName)
       where T : DependencyObject
    {    
      // Confirm parent and childName are valid. 
      if (parent == null) return null;

      T foundChild = null;

      int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
      for (int i = 0; i < childrenCount; i++)
      {
        var child = VisualTreeHelper.GetChild(parent, i);
        // If the child is not of the request child type child
        T childType = child as T;
        if (childType == null)
        {
          // recursively drill down the tree
          foundChild = FindChild<T>(child, childName);

          // If the child is found, break so we do not overwrite the found child. 
          if (foundChild != null) break;
        }
        else if (!string.IsNullOrEmpty(childName))
        {
          var frameworkElement = child as FrameworkElement;
          // If the child's name is set for search
          if (frameworkElement != null && frameworkElement.Name == childName)
          {
            // if the child's name is of the request name
            foundChild = (T)child;
            break;
          }

 // recursively drill down the tree
          foundChild = FindChild<T>(child, childName);

          // If the child is found, break so we do not overwrite the found child. 
          if (foundChild != null) break;


        else
        {
          // child element found.
          foundChild = (T)child;
          break;
        }
      }

      return foundChild;
    }  

तुम बस (यह होता है जब आप पारित विधि रिकर्सिवली यदि प्रकार मिलान कर रहे हैं, लेकिन नाम नहीं बुला जारी रखने की आवश्यकता FrameworkElementके रूप में T)। अन्यथा यह वापसी करने वाला है nullऔर यह गलत है।


0

कोड से दिए गए प्रकार के पूर्वजों को खोजने के लिए, आप इसका उपयोग कर सकते हैं:

[CanBeNull]
public static T FindAncestor<T>(DependencyObject d) where T : DependencyObject
{
    while (true)
    {
        d = VisualTreeHelper.GetParent(d);

        if (d == null)
            return null;

        var t = d as T;

        if (t != null)
            return t;
    }
}

यह कार्यान्वयन पुनरावृत्ति के बजाय पुनरावृत्ति का उपयोग करता है जो थोड़ा तेज़ हो सकता है।

यदि आप C # 7 का उपयोग कर रहे हैं, तो इसे थोड़ा छोटा किया जा सकता है:

[CanBeNull]
public static T FindAncestor<T>(DependencyObject d) where T : DependencyObject
{
    while (true)
    {
        d = VisualTreeHelper.GetParent(d);

        if (d == null)
            return null;

        if (d is T t)
            return t;
    }
}

-5

इसे इस्तेमाल करे

<TextBlock x:Name="txtblock" FontSize="24" >Hai Welcom to this page
</TextBlock>

कोड के पीछे

var txtblock = sender as Textblock;
txtblock.Foreground = "Red"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.