নাম বা প্রকারের মাধ্যমে আমি কীভাবে ডাব্লুপিএফ নিয়ন্ত্রণগুলি পেতে পারি?


264

প্রদত্ত নাম বা প্রকারের সাথে মেলে এমন নিয়ন্ত্রণগুলির জন্য আমাকে একটি ডাব্লুপিএফ নিয়ন্ত্রণ নিয়ন্ত্রণ স্তর অনুসন্ধান করতে হবে। কিভাবে আমি এটি করতে পারব?

উত্তর:


311

আমি জন মাইজেক এবং ট্রাই কিউ এর অ্যালগরিদম দ্বারা ব্যবহৃত টেমপ্লেট ফর্ম্যাটটি একত্রে একটি ফাইন্ডচিল্ড অ্যালগরিদম তৈরি করেছি যা কোনও পিতামাতার উপর ব্যবহার করা যেতে পারে। মনে রাখবেন যে পুনরাবৃত্তভাবে নীচের দিকে একটি গাছ অনুসন্ধান করা একটি দীর্ঘ প্রক্রিয়া হতে পারে। আমি কেবলমাত্র ডাব্লুপিএফ অ্যাপ্লিকেশনটিতে এটি স্পট-চেক করেছি, আপনি যে কোনও ত্রুটি খুঁজে পেতে পারেন সে সম্পর্কে মন্তব্য করুন এবং আমি আমার কোডটি সংশোধন করব।

ডাব্লুপিএফ স্নুপ ভিজ্যুয়াল ট্রি দেখার জন্য একটি দরকারী সরঞ্জাম - আমি আপনার কাজটি যাচাই করার জন্য এই অ্যালগরিদমটি পরীক্ষা করার সময় বা ব্যবহার করার সময় দৃ strongly়তার সাথে এটি ব্যবহার করার পরামর্শ দিই।

ট্রাই কিউজের অ্যালগোরিদমে একটি ছোট্ট ত্রুটি রয়েছে। সন্তানের সন্ধান পাওয়ার পরে, যদি চাইল্ডসউন্টটি 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যে কোনও প্যারেন্ট উইন্ডো হতে পারে।


@ ক্রিমসনএক্স: সম্ভবত আমি এই ভুলটি করছি ... আমার কন্টেন্টকন্ট্রোলের (এক্সপেন্ডার) ভিতরে নিয়ন্ত্রণ (লিস্টবক্স) পেতে আমারও একইরকম প্রয়োজন ছিল। উপরের কোডটি আমার পক্ষে সেভাবে কাজ করে নি .. একটি লিফ নোড (গেটচিল্ডারকাউন্ট => 0) কোনও সামগ্রী নিয়ন্ত্রণ রয়েছে কিনা তা জানতে আমাকে উপরের কোডটি আপডেট করতে হয়েছিল। যদি হ্যাঁ, বিষয়বস্তুটির নাম + টাইপ মানদণ্ডের সাথে মেলে কিনা তা পরীক্ষা করে দেখুন।
গিশু

@ গিশু - আমি মনে করি এটি এই উদ্দেশ্যে কাজ করা উচিত। আপনি কীভাবে কলটি ব্যবহার করছেন তা দেখাতে আপনি কি আপনার কোড অনুলিপি এবং আটকানোতে পারেন? আমি আশা করব এটি ফাইন্ডহিল্ড <লস্টবক্স> (এক্সপেন্ডার মাইএক্সপান্ডারনাম, "মাইলিস্টবক্সনাম") হওয়া উচিত।
ক্রিমসনএক্স

3
@ ক্রিমসনএক্স আমি মনে করি যে আমি একটি অন্য কোণার কেস পেয়েছি। আমি রিবন অ্যাপ্লিকেশনমেনুআইটিমে পিন্টিস্টসবুমেনুপ্লেসোল্ডার সন্ধানের চেষ্টা করছিলাম, তবে উপরের কোডটি কাজ করছে না। এটি সমাধানের জন্য, আমাকে নিম্নলিখিতগুলি যুক্ত করতে হবে: যদি (নাম == এলিমেন্টনাম) অন্য if ফাউন্ডচিল্ড = ফাইন্ডচাইল্ড (শিশু, নাম) যদি (foundChild! = নাল) বিরতি; }
কেভিন্দুব

6
দয়া করে সাবধান থাকুন, উত্তরে বাগ বা আরও কিছু রয়েছে। এটি অনুসন্ধানের ধরণের কোনও সন্তানের কাছে পৌঁছানোর সাথে সাথে এটি বন্ধ হয়ে যাবে। আমি মনে করি আপনার অন্যান্য উত্তরগুলি বিবেচনা করা / অগ্রাধিকার দেওয়া উচিত।
এরিক ওয়েললেট

2
এই কোডটি দুর্দান্ত, তবে আপনি যদি কোনও নির্দিষ্ট ধরণের উপাদান অনুসন্ধান না করেন তবে এটি কাজ করবে না, উদাহরণস্বরূপ আপনি যদি FrameworkElementটি হিসাবে পাস করেন তবে প্রথম লুপ শেষ হওয়ার সাথে সাথে এটি বাতিল হয়ে যাবে। সুতরাং আপনার কিছু পরিবর্তন করতে হবে।
আমির ওভেসি

131

ফ্রেমওয়ার্কএলমেন্ট.ফাইন্ডনাম (স্ট্রিং) ব্যবহার করে আপনি নামের মাধ্যমে একটি উপাদানও খুঁজে পেতে পারেন ।

প্রদত্ত:

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

কোড-পেছনের ফাইলটিতে আপনি লিখতে পারেন:

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

অবশ্যই, এটি এক্স: নাম ব্যবহার করে সংজ্ঞায়িত করা হয়েছে, আপনি কেবল উত্পন্ন ক্ষেত্রটি উল্লেখ করতে পারেন, তবে সম্ভবত আপনি এটিকে স্থিতির চেয়ে গতিশীলভাবে দেখতে চান।

এই পদ্ধতিটি টেমপ্লেটগুলির জন্যও উপলভ্য, এতে নামযুক্ত আইটেমটি একাধিকবার প্রদর্শিত হয় (একবারে টেমপ্লেটের ব্যবহারের জন্য)।


6
এটি কাজ করার জন্য আপনাকে অবশ্যই নাম অ্যাট্রিবিউটে "x:" যুক্ত করতে হবে না।
ব্রায়ান বক

3
এটি সর্বদা কাজ করে না বলে মনে হয়। আমার কাছে ইউজারকন্ট্রোল রয়েছে যা কোনও প্রোপার্টি উইন্ডোর সামগ্রী হিসাবে নেস্টেড গ্রিডগুলিতে প্রোগ্রামেমেটিকভাবে একত্রিত হয়। ক্রিমসনএক্স এর উত্তরটি ঠিক কাজ করে।
ম্যাট

4
এটি আইটেমকন্ট্রোল, লিস্টবক্স ইত্যাদি ইত্যাদির জন্য কাজ করবে না
সোরেনসেন

67

আপনি নিয়ন্ত্রণগুলি পেতে ভিজুয়ালটিহেল্পার ব্যবহার করতে পারেন । নীচে এমন একটি পদ্ধতি রয়েছে যা একটি নির্দিষ্ট ধরণের পিতামাতার নিয়ন্ত্রণ পেতে ভিজুয়ালটিহেল্পার ব্যবহার করে। আপনি অন্যান্য উপায়ে নিয়ন্ত্রণগুলি খুঁজতে ভিজুয়ালটিহেল্পার ব্যবহার করতে পারেন।

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

আপনি কীভাবে পাবেন বা মাই কন্ট্রোল কী?
দেমডাভ

21

আমি কেবল অন্য সবাইকে পুনরাবৃত্তি করতে পারি তবে আমার কাছে কোডের একটি সুন্দর টুকরো রয়েছে যা ডিপেন্ডেন্সিঅবজেক্ট শ্রেণিকে একটি পদ্ধতি ফাইন্ডহাইল্ড () দিয়ে প্রসারিত করে যা আপনাকে টাইপ এবং নাম দিয়ে বাচ্চাটি পাবে। শুধু অন্তর্ভুক্ত এবং ব্যবহার।

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/...
CrimsonX

18

কোডটিতে আমার এক্সটেনশানগুলি।

  • টাইপ এবং মানদণ্ডের (প্রিডিকেট) অনুসারে একটি বাচ্চাকে খুঁজে পেতে ওভারলোডগুলি যুক্ত করা হয়েছে, মানদণ্ডগুলি পূরণ করে এমন সমস্ত শিশুদের সন্ধান করুন
  • ডিপেন্ডেন্সিঅবজেক্টের জন্য এক্সটেনশন পদ্ধতি ছাড়াও ফাইন্ডচিল্ডেন পদ্ধতিটি একটি পুনরাবৃত্তকারী
  • ফাইন্ডচিল্ডার যৌক্তিক উপ-গাছগুলিতেও হাঁটেন। জোশ স্মিথের পোস্টটি ব্লগ পোস্টে লিঙ্কে দেখুন।

উত্স: https://code.google.com/p/gishu-util/source/browse/#git%2FWPF%2F ইউটিলিটি

ব্যাখ্যামূলক ব্লগ পোস্ট: http://madcoderspeak.blogspot.com/2010/04/wpf-find-child-control-of-specific-type.html


-1 ঠিক কীভাবে আমি বাস্তবায়ন করতে যাচ্ছিলাম (প্রিডিকেট, ইেটরেটর এবং এক্সটেনশন পদ্ধতি), তবে উত্সের লিঙ্কটিতে একটি 404 রয়েছে। কোডটি এখানে অন্তর্ভুক্ত করা হলে +1 এ পরিবর্তিত হবে বা উত্সের লিঙ্কটি স্থির হয়ে গেছে!
cod3monk3y

@ cod3monk3y - গীত মাইগ্রেশন লিংক মনে হয় :) এখানে নিহত আপনি যেতে .. 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
ভাল তবে কন্ট্রোলটি লোড হয়েছে তা নিশ্চিত করুন অন্যথায় গেটচিলড্রাউন্ট 0 ফিরে আসবে
ক্লাউস এনজি

@ উরবানএস্ক, আপনি childদ্বিতীয়বার কেন ভোট দিচ্ছেন ? যদি আপনার childTypeটাইপ থাকে তবে আপনি Tভিতরে লিখতে পারেন if: yield return childType... না?
ম্যাসিমিলিয়ানো ক্রাউস

@ মাসিমিলিয়ানো ক্রাউস আরে, দেরিতে সাড়া পাওয়ার জন্য দুঃখিত, তবে আপনি ঠিক বলেছেন। আমি এই স্নিপেটটি বেশ কয়েকবার পুনরায়
লেখার

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)
ড্রু নোকস

@ ড্রউনোকস ফিলিপকে কী ডাকার পরামর্শ দিচ্ছেন, তাহলে? এছাড়াও, এমন প্রত্যাশার সাথেও আমি তার কোডটি ব্যবহারের জন্য পরিষ্কার এবং স্পষ্ট দেখতে পেয়েছি।
আনবিস

1
@ নবীন, এই ক্ষেত্রে আমি কেবল এটি কল করব 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 বছর আগের থেকে, তাই এটি আর কাজ করে কিনা আমি এমনকি জানি না :)
10-15 এহেন্দ্রিকতা

আমি কেবল এটি উল্লেখ করেছি, কারণ আমি এতে হোঁচট
অন্যরাও

13

যদিও আমি সাধারণভাবে পুনরাবৃত্তি পছন্দ করি, সি # তে প্রোগ্রামিং করার সময় এটি পুনরাবৃত্তির মতো দক্ষ নয়, সুতরাং জন মাইজেজকের পরামর্শ অনুসারে নীচের সমাধানটি আরও কম? এটি কোনও নির্দিষ্ট ধরণের পূর্বপুরুষের নিয়ন্ত্রণ পেতে প্রদত্ত নিয়ন্ত্রণ থেকে একটি শ্রেণিবিন্যাস অনুসন্ধান করে।

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

আমরা হায়ারার্কিতে কত গভীর যেতে পারি তা নিয়ন্ত্রণ করতে গিয়ে টাইপ অনুসারে নিয়ন্ত্রণগুলি খুঁজতে আমার কোড এখানে রয়েছে (ম্যাক্সডেপথ == 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 ... আপনার কোডটি ইউজারকন্ট্রোলগুলির মাধ্যমে পুনরাবৃত্তি না করায় আমার সমস্যা ছিল। এটি গ্রিডের মূলটিকে আঘাত করছে এবং একটি ত্রুটি ছুঁড়েছিল। আমি বিশ্বাস করি এটি আমার জন্য এটি ঠিক করে দেয়:

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());
    }

সমস্ত নিয়ন্ত্রণ পেতে আপনি উইন্ডোতে এটি কল করতে পারেন।

আপনার সংগ্রহটি শেষ হওয়ার পরে, আপনি লিনকুই (অর্থাত্ টাইপ, যেখানে) ব্যবহার করতে পারেন।


6

যেহেতু প্রশ্নটি যথেষ্ট সাধারণ যে এটি খুব তুচ্ছ মামলার জবাব খুঁজছেন এমন লোকদের আকর্ষণ করতে পারে: আপনি যদি বংশধরের চেয়ে কেবল সন্তান চান, আপনি লিনক ব্যবহার করতে পারেন:

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

এই বিকল্পগুলি ইতিমধ্যে সি # তে ভিজ্যুয়াল ট্রিটি অতিক্রম করার কথা বলে। এক্সএএমএলে ভিজ্যুয়াল ট্রি অতিক্রম করার পাশাপাশি রিলেটিভসোর্স মার্কআপ এক্সটেনশন ব্যবহার করে এটি সম্ভব। 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

এই কোডটি কেবলমাত্র ক্রিমসনএক্স উত্তরের বাগটি ঠিক করেছে:

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

আপনি শুধু (এই ঘটে যখন আপনি পাস পদ্ধতি যাও recursively যদি ধরনের মিলে কতগুলো নাম বৈ নয় না কলিং চালিয়ে যাবার প্রয়োজন 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;
    }
}

এই প্রয়োগটি পুনরাবৃত্তির পরিবর্তে পুনরাবৃত্তি ব্যবহার করে যা কিছুটা দ্রুত হতে পারে।

আপনি যদি সি # 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"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.