Как я могу найти средства управления WPF по имени или тип?

Вы можете установить разные стили на разных серверах, добавив название стиля в конфигурационном файле.

  //require config.js and it can be like this:   

  var environments = {};        

  environments.staging = {        
      'httpPort': 3000,        
      'envName': 'staging',        
      'style': 'red.scss'
  }        

  environments.production = {        
      'httpPort': 5000,        
      'envName': 'production',        
      'style': 'green.scss'        
  }        

  var currentEnvironment = typeof(process.env.NODE_ENV) == 'string' ? process.env.NODE_ENV : '';        
  var environmentToExport = typeof(environments[currentEnvironment]) == 'object' ? environments[currentEnvironment] : environments.staging;        

  module.exports = environmentToExport;        
258
задан Shog9 6 February 2014 в 05:17
поделиться

7 ответов

Я объединил формат шаблона, используемый Джоном Мичеком, и алгоритм Tri Q, описанный выше, чтобы создать алгоритм findChild, который можно использовать для любого родителя. Имейте в виду, что рекурсивный поиск дерева вниз может быть длительным процессом. Я только выборочно проверил это в приложении WPF, прокомментируйте любые ошибки, которые вы можете найти, и я исправлю свой код.

WPF Snoop - полезный инструмент для просмотра визуального дерева - я настоятельно рекомендую использовать его при тестировании или использовать этот алгоритм для проверки вашей работы.

В алгоритме Tri Q есть небольшая ошибка. После того, как дочерний элемент найден, если childrenCount> 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 может быть любым родительским окном.

300
ответ дан 23 November 2019 в 02:41
поделиться

Можно использовать 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);
66
ответ дан John Myczek 23 November 2019 в 02:41
поделиться

Это отклонит некоторые элементы - вам следует расширить его таким образом, чтобы поддерживать более широкий набор элементов управления. Для краткого обсуждения см. здесь

 /// <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);
   }
}
16
ответ дан 23 November 2019 в 02:41
поделиться

Вы также можете найти элемент по имени, используя FrameworkElement.FindName (string) .

Дано:

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

В файле кода программной части вы можете написать :

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

Конечно, поскольку он определен с использованием x: Name, вы можете просто сослаться на сгенерированное поле, но, возможно, вы захотите найти его динамически, а не статически.

Этот подход также доступен для шаблонов, в которых именованный элемент появляется несколько раз (один раз за одно использование шаблона).

124
ответ дан 23 November 2019 в 02:41
поделиться

Я могу просто повторять всех остальных, но у меня есть красивый фрагмент кода, который расширяет класс DependencyObject с помощью метода FindChild (), который доставит вам ребенка по типу и имени. Просто включите и используйте.

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

Надеюсь, вы сочтете это полезным.

21
ответ дан 23 November 2019 в 02:41
поделиться

Мои расширения кода.

  • Добавлены перегрузки для поиска одного дочернего элемента по типу, по типу и критериям (предикат), поиск всех дочерних элементов типа, которые соответствуют критериям
  • , метод FindChildren является итератором в дополнение к методу расширения для DependencyObject
  • FindChildren также обходит логические поддеревья. См. Сообщение Джоша Смита по ссылке в блоге.

Источник: https://code.google.com/p/gishu-util/source/browse/#git%2FWPF%2FUtilities

Пояснительная запись в блоге: {{1} } http://madcoderspeak.blogspot.com/2010/04/wpf-find-child-control-of-specific-type.html

18
ответ дан 23 November 2019 в 02:41
поделиться

Я отредактировал код CrimsonX, так как он не работал с типами суперклассов:

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;
}
16
ответ дан 23 November 2019 в 02:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: