Модераторы: gambit, Kefir, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> не получается найти объект через "FindName", FindName 
:(
    Опции темы
Compositum
Дата 12.9.2009, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 430
Регистрация: 6.1.2008
Где: Санкт-Петербург

Репутация: 1
Всего: 1



Не удаётся найти объект, содержащийся в экземпляре Window через задействование метода FindName этого экземпляра. Петцольд (стр. 100) - экземпляр окна должен при поиске пройтись по всей иерархии вложенных объектов. 
На практике получаю иной результат. Не находит даже то, что назначено непосредственно свойству Content окна:

Код

Window win = new Window();
ScrollViewer scroll = new ScrollViewer();
scroll.Name = "scroll";
win.Content = scroll;
ScrollViewer sc = win.FindName("scroll") as ScrollViewer;//Получаю Null

не срабатывает и такой пример (для разнообразия):
Код

            Window win = new Window();
            StackPanel stackPan = new StackPanel();
            for (int i = 0; i < 5; i++)
            {
                TextBlock txtBlock = new TextBlock { Name = "textBlock_" + i };
                stackPan.Children.Add(txtBlock);
            }
            win.Content = stackPan;
            TextBlock result = stackPan.FindName("textBlock_3") as TextBlock;
            Console.WriteLine("Result for stackPan.FindName: {0}", result == null ? false : true);// result: False. Why?
            result = win.FindName("textBlock_3") as TextBlock;
            Console.WriteLine("Result for win.FindName: {0}", result == null ? false : true);// result: False. Why?

Почему?
П.С. Информация из МСДН (с рассмотрением прилагаемого примера) не помогла...

Это сообщение отредактировал(а) Compositum - 13.9.2009, 11:30
PM   Вверх
Compositum
Дата 13.9.2009, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 430
Регистрация: 6.1.2008
Где: Санкт-Петербург

Репутация: 1
Всего: 1



Попробовал написать свою версию реализации данного метода.
Код:
Код

    /// <summary>
    /// Мой некоторый класс, содержаший расширяющие методы...
    /// </summary>
    public static class MyExtendedMetods
    {
        /// <summary>
        /// Мой вариант реализации метода, подобного Framework.FindName(string name)...
        /// </summary>
        /// <param name="source">родительский экземпляр класса FrameworkElement, в котором предстоит осуществлять поиск элемента по имени</param>
        /// <param name="name">имя элемента, который должен быть найден.</param>
        /// <returns>Возвращается экземпляр класса FrameworkElement. Если элемент не найден - возвращается null.</returns>
        public static FrameworkElement FindByName(this FrameworkElement source, string name)
        {
            PropertyInfo property = source.GetType().GetProperty("VisualChildrenCount", 
     BindingFlags.Instance | BindingFlags.NonPublic);
            int childCount = (int) property.GetValue(source, null);            
            MethodInfo method = source.GetType().GetMethod("GetVisualChild", BindingFlags.Instance |   
     BindingFlags.NonPublic);            
            for (int i = 0; i < childCount; i++)
            {                
                FrameworkElement item = ((FrameworkElement) method.Invoke(source, new object[] {i}));
                if (item.Name == name) return item;
                item.FindByName(name);
            }
            return null;
        }
    }

Но снова получаю проблему (смотреть комментарии):
Код

Window win = new Window{Name = "win"};
TreeView tree = new TreeView { Name = "tree" };
StackPanel stackPan = new StackPanel {Orientation = Orientation.Horizontal, 
Name = "stack"};
CheckBox checkBox = new CheckBox {IsChecked = null, Name = "chBox"};        
stackPan.Children.Add(checkBox);
TextBlock checkText = new TextBlock(new Run("My Checked Item"));
stackPan.Children.Add(checkText);
tree.Items.Add(stackPan);
win.Content = tree;

FrameworkElement element = stackPan.FindByName("chBox"); //здесь получаю верный результат

///Внимание!!! Как это ни странно, далее  protected virtual VisualChildrenCount property для экземпляров 
///'win' и 'tree' возвращает ноль...
element = tree.FindByName("chBox");//не верный результат,
//потому, что свойство 'VisualChildrenCount' содержит 0 !!!

element = win.FindByName("chBox");//не верный результат,
//потому, что свойство 'VisualChildrenCount' содержит 0 !!!


Напрашивается мысль, мол проблема в том, что для классов Window и TreeView не корректно реализовано защищенное виртуальное свойство VisualChildrenCount property в библиотеке '.Net Framework', поскольку имея дочерние элементы данное свойство должно возвращать их количество. В указанном выше примере видно, что в данной позиции идет несостыковка. Однако если бы этот баг имел место быть, то невозможно было бы реализовывать для экземпляров данных классов свойства зависимостей или маршрутизация событий. 

Почему свойство VisualChildrenCount возвращает 0 ?
PM   Вверх
Compositum
Дата 13.9.2009, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 430
Регистрация: 6.1.2008
Где: Санкт-Петербург

Репутация: 1
Всего: 1



выглядит это так:

user posted image
PM   Вверх
Compositum
Дата 14.9.2009, 08:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 430
Регистрация: 6.1.2008
Где: Санкт-Петербург

Репутация: 1
Всего: 1



насчет FrameworkElement.FindName вопрос снят - нужно в коде дополнительно заюзать NameScope.
Код

 static void Main()
        {
            Window win = new Window { Name = "win" };

            INameScope s = new NameScope();
            NameScope.SetNameScope(win, s);

            ScrollViewer scroll = new ScrollViewer { Name = "scroll" };
            win.Content = scroll;
            
            
            TreeView tree = new TreeView { Name = "tree" };
            scroll.Content = tree;           

            StackPanel stackPan = new StackPanel { Orientation = Orientation.Horizontal, Name = "stack" };
            CheckBox checkBox = new CheckBox { IsChecked = null, Name = "chBox" };
            stackPan.Children.Add(checkBox);
            TextBlock checkText = new TextBlock(new Run("My Checked Item"));
            stackPan.Children.Add(checkText);
            tree.Items.Add(stackPan);

            ////1-й вариант регистрации:
            //win.RegisterName("scroll", scroll);
            //win.RegisterName("tree", tree);
            //win.RegisterName("stack", stackPan);            
            //win.RegisterName("chBox", checkBox);

            ////2-й вариант регистрации:
            //s.RegisterName("win", win);
            //s.RegisterName("scroll", scroll);
            //s.RegisterName("tree", tree);
            //s.RegisterName("stack", stackPan);
            //s.RegisterName("chBox", checkBox);

            //3-й вариант регистрации:
            s.RegisterName("win", win);
            win.RegisterName("scroll", scroll);
            scroll.RegisterName("tree", tree);
            tree.RegisterName("stack", stackPan);
            stackPan.RegisterName("chBox", checkBox);
            
            FrameworkElement element = stackPan.FindByName("chBox"); 
            element = (CheckBox) tree.FindName("chBox");
            element = (TreeView) scroll.FindName("tree");
            element = (ScrollViewer) win.FindName("scroll");
            Application app = new Application();
            app.Run(win);
...

Однако касательно того, почему свойство FrameworkElement.VisualChildrenCount для озвученных выше элементов равнялось нулю - вопрос так и остается пока не решенным... =((((
PM   Вверх
math64
Дата 16.9.2009, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 2
Всего: 72



Может быть это из-за того, что app.Run() ещё не запущено?

А как быть здесь, регистрацию не сделаешь, компонент создавал не я:
Код

  public class MyControl : Control
  {

    protected override Size ArrangeOverride(Size arrangeBounds)
    {
      double w = arrangeBounds.Width;
      double h = arrangeBounds.Height;
      Line line = FindName("line") as Line;
      line.X1 = w / 2;
      line.Y1 = h / 2;
      line.X2 = w * 0.85; // w*0.5*(1+Math.cos(Math.PI/4));
      line.Y2 = h * 0.15; // h*0.5*(1-Math.sin(Math.PI/4));
      return base.ArrangeOverride(arrangeBounds);
    }
  }

Код

    <Style TargetType="{x:Type local:MyControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MyControl}">
                    <Grid Name="grid">
                        <Ellipse Name="ellipse" Stroke="Red" StrokeThickness="1"/>
                        <Line Name="line" Stroke="Blue" StrokeThickness="1" X1="10"  Y1="10"  X2="17"  Y2="3"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

PM   Вверх
math64
Дата 17.9.2009, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 2
Всего: 72



В моём случае нужно вызывать
Код

Line line = Template.FindName("line", this) as Line;

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | WPF и Silverlight | Следующая тема »


 




[ Время генерации скрипта: 0.0604 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.