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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Самопроизвольное перемещение по древу компонентов 
:(
    Опции темы
Compositum
Дата 2.4.2010, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


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

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



Хочу подробней изучить шаблоны стандартных контролов WPF. 
Для этого извлекаю интересующие меня контролы из стандартной сборки .Net Framework 3.5 SP1, формируя из их имён иерархию в объекте TreeView. При клике мышки на имени класса получаю в верхней правой части окна экземпляр выбранного класса, а в нижней - XAML-код визуального дерева элемента. 

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

user posted image

Но есть проблема: 
Поскольку класс Window и его наследников нельзя использовать в качестве элемента содержимого, то при клике на этих классах (их там два, как видим из скрина) я открываю экземпляр выбранного класса в виде отдельного дочернего окна. Проблема заключается в том, что если я в TreeView кликну мышью на элементе NavigationWindow (см. скрин), то сразу после открытия экземпляра класса NavigationWindow, в дереве происходит самопроизвольнное назначение выбранным элементом тот, который находится на один уровень выше указанного мною, создавая и отображая тем самым экземпляр класса Window (поскольку именно он расположен выше), после чего тут же происходит ещё один аналогичный переход на один уровень выше и выбирается элемент ContentControl. 

В результате у меня получается открыто два окна (одно - NavigationWindow и одно - Window), выбранным в TreeView оказывается элемент ContentControl, и шаблон, соответственно, отображается его же...

Не раз в отладчике прошелся построчно с F11, но так и не понял, почему происходит самопроизвольный переход. Причём это происходит только при выборе в древе элемента NavigationWindow или же при выборе Window. Все остальные работают как нужно...
Исходный код:
Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using System.Windows.Markup;
using System.Reflection;

namespace VisualTreeViewer
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        TextBox txtBox;
        Grid grid;

        public Window1()
        {
            InitializeComponent();
            Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
            MyInitialize();            
        }
        void MyInitialize()
        {
            //Формирую список элементов
            TreeViewItem[] items = typeof(Control).Assembly.GetTypes()
                .Where(n => n.IsPublic && (n.IsSubclassOf(typeof(Control)) || 
                    n == typeof(Control))).OrderBy(n => n.Name).Select(n => new TreeViewItem {Header = n.Name, Tag = n}).ToArray();

            //Реализовываю иерархию элементов
            IEnumerable<TreeViewItem> items2 = items.Select(n => { n.ItemsSource = items.Where(m => (m.Tag as Type)
                .BaseType.Name == (n.Header as string)); return n;});

            ScrollViewer sv = new ScrollViewer()
            {
                HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
                VerticalScrollBarVisibility = ScrollBarVisibility.Auto
            };

            //В качестве источника данных назначаю корневой элемент иерархии классов
            TreeView tv = new TreeView() { ItemsSource = items2.Where(n => (n.Header as string) == "Control") };

            //В результате работы кода TreeView содержит только первый уровень вложенности
            sv.Content = tv;            
            Title = "Просмотр визуального дерева (состав шаблона) стандартных компонентов WPF.";
            grid = new Grid();
            GridLength[] gridLengths = new GridLength[] { new GridLength(3, GridUnitType.Star), GridLength.Auto, new GridLength(7, GridUnitType.Star) };
            for (int i = 0; i < 3; i++)
            {
                RowDefinition row = new RowDefinition() { Height = gridLengths [i]};
                grid.RowDefinitions.Add(row);
            }
            for (int i = 0; i < 3; i++)
            {
                ColumnDefinition column = new ColumnDefinition(){Width=gridLengths[i]};
                grid.ColumnDefinitions.Add(column);
            }
            grid.Children.Add(sv);
            Grid.SetRowSpan(sv, grid.RowDefinitions.Count);
            GridSplitter vertSplitter = new GridSplitter() { Width = 5, HorizontalAlignment = HorizontalAlignment.Center };
            grid.Children.Add(vertSplitter);
            Grid.SetColumn(vertSplitter, 1);
            Grid.SetRowSpan(vertSplitter, grid.RowDefinitions.Count);

            GridSplitter horSplitter = new GridSplitter() { Height = 5, HorizontalAlignment = HorizontalAlignment.Stretch};
            grid.Children.Add(horSplitter);
            Grid.SetRow(horSplitter, 1);
            Grid.SetColumn(horSplitter, 2);

            txtBox = new TextBox();

            ScrollViewer sv2 = new ScrollViewer()
            {
                HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
                VerticalScrollBarVisibility = ScrollBarVisibility.Auto
            };
            sv2.Content = txtBox;
            grid.Children.Add(sv2);
            Grid.SetColumn(sv2, 2);
            Grid.SetRow(sv2, 2);            
            txtBox.AcceptsReturn = true;
            Background = Brushes.Gray;
            tv.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(tv_SelectedItemChanged);

            Content = grid;
        }

        void tv_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            Control[] cls = grid.Children.Cast<Control>().Where(n => Grid.GetRow(n) == 0 && Grid.GetColumn(n) == 2).ToArray();
            foreach (Control item in cls)
            {
                grid.Children.Remove(item);
            }
            txtBox.Clear();
            Type type = (e.NewValue as TreeViewItem).Tag as Type;
            
            ConstructorInfo ci = type.GetConstructor(System.Type.EmptyTypes);
            Control ctrl = null;
            try
            {
                ctrl = (Control)ci.Invoke(null);
                if (ctrl is Window)
                {
                    Window win = ctrl as Window; win.Width = 300; win.Height = 300;
                    ShowWindow(win);                                      
                }
                else
                {
                    ShowXaml(ctrl);
                }
            }
            catch (Exception ex)
            {
                if (type.IsAbstract)
                {
                    MsgShow("Класс является абстрактным.");
                }
                else if (ctrl == null)
                {
                    MsgShow("Класс не содержит конструктора по умолчанию.");
                }
                else if (ctrl.Template == null)
                {
                    MsgShow("Выбранный класс не имеет шаблона.");
                }
                else
                {
                    MsgShow(ex.Message);
                }                
            }
        }

        private void ShowXaml(Control ctrl)
        {
            StringBuilder sb = new StringBuilder();
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.IndentChars = new string(' ', 4);
            settings.NewLineOnAttributes = true;
            XmlWriter xw = XmlWriter.Create(sb, settings);
            grid.Children.Add(ctrl);
            Grid.SetColumn(ctrl, 2);
            ctrl.Margin = new Thickness(10);
            XamlWriter.Save(ctrl.Template, xw);
            txtBox.Text = sb.ToString();
        }

        private void ShowWindowXaml(Window ctrl)
        {
            StringBuilder sb = new StringBuilder();
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.IndentChars = new string(' ', 4);
            settings.NewLineOnAttributes = true;
            XmlWriter xw = XmlWriter.Create(sb, settings);            
            XamlWriter.Save(ctrl.Template, xw);
            txtBox.Text = sb.ToString();
        }

        private void ShowWindow(Window win)
        {
            win.Owner = this;
            win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            win.Topmost = true;
            win.Show();
            ShowWindowXaml(win);
        }

        private void MsgShow( string txt)
        {
            Label tblock = new Label() { Content = txt };
            grid.Children.Add(tblock);
            Grid.SetColumn(tblock, 2);
            tblock.HorizontalAlignment = HorizontalAlignment.Center;
            tblock.VerticalAlignment = VerticalAlignment.Center;
        }
    }
}

если немного изменить метод ShowWindow(Window win) так:
Код

        private void ShowWindow(Window win)
        {
            win.Owner = this;
            win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            win.Topmost = true;
            win.Show();            
            ShowWindowXaml(win);
            win.Close();//Добавил эту строку
        }

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

Почему так происходит?

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


 




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


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

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