2017-02-07 18 views
0

В моем проекте я должен использовать WPF для размещения большого набора похожих элементов управления пользователя (около 2000) на объекте Canvas. В принципе, это всего лишь набор прямоугольников, которые могут изменять видимость, можно выбирать и хранить объект данных внутри.Вызов LoadBaml() один раз для набора аналогичных элементов управления пользователя

добавить новые элементы управления с помощью вложенного свойства следующим образом:

public static readonly DependencyProperty VisualStaticBlocksProperty = 
     DependencyProperty.RegisterAttached("VisualStaticBlocks", typeof(ObservableCollection<VisualBlockViewModel>), typeof(BindableBlocksBehaviour), 
     new UIPropertyMetadata(null, VisualStaticBlocksPropertyChanged)); 

    private static void VisualStaticBlocksPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
    { 
     ClickSightView clickSight = source as ClickSightView; 
     ObservableCollection<VisualBlockViewModel> visualBlocks = e.NewValue as ObservableCollection<VisualBlockViewModel>; 
     if (clickSight != null && visualBlocks != null) 
     { 
      foreach (VisualBlockViewModel visualBlock in visualBlocks) 
      { 
       clickSight.StaticBlocksCanvas.Children.Add(new VisualBlockView(visualBlock)); 
      } 
     } 
    } 

Однако, это занимает много времени, чтобы построить все из них (около 2 секунд). Я использовал профилировщик, чтобы проверить, что основная проблема заключается в методе LoadBaml(), который вызывается в методе InitializeComponent().

Как я понимаю, LoadBaml() используется для разбора разметки xaml. Возможно ли каким-то образом кэшировать результат LoadBaml() для компонента и повторно использовать его вместо parse xaml каждый раз, когда я создаю новый экземпляр управления?

EDIT: Чтобы представить этот набор объектов визуально я создал пользовательский элемент управления с Canvas на нем, и созданный вложенное свойство VisualStaticBlocks для attachblock просмотра моделей (тип VisualBlockViewModel) к этому элементу управления и вставить визуальный блок экземпляры (тип VisualBlockView) прямо на холст.

EDIT2: Я решил проблему, отказавшись от использования пользовательских элементов управления для этой цели. Поскольку мои элементы управления довольно просты, я использовал Rectangle() вместо 3 добавленных вручную привязок и 3 добавленных вручную события. Конечно, вообще не было вызовов InitializeComponent(). Это позволило мне создать набор из 2000 прямоугольников в 200 миллисекунд, что в 10 раз быстрее. В любом случае, будем благодарны за информацию, если я могу клонировать подобные объекты, не загружая BAML каждый раз.

+0

Пожалуйста, не задавайте вопросы типа «помогите мне». На ваш вопрос не хватает информации. Пожалуйста, прочитайте http://stackoverflow.com/help/how-to-ask –

+0

Извините, я прочитал FAQ и до сих пор не понимаю, какую другую информацию я должен предоставить здесь. Можете ли вы уточнить, какая информация отсутствует? –

ответ

0

Похоже, что у вас есть проблема с тем временем, которое требуется для создания визуальных элементов. Я понимаю, почему вы думаете, что вам нужно позвонить InitializeComponent, но это не то, как работает WPF.

В noted here:

Вызов InitializeComponent() (который обычно называют в конструктор по умолчанию, по меньшей мере, окна и UserControl) на самом деле является вызов метода к частичному классу управления (а не вызовите иерархию объектов, как я и ожидал).

В результате я подозреваю, что вы не понимаете, как (или почему) InitializeComponent работ; его невозможно вызвать один раз, чтобы создать несколько элементов и извне, не меньше.

Вы используете ObservableCollection, который не работает хорошо с большими наборами данных или с комплексными видами. Подумайте об использовании потокобезопасного ObservableCollection и добавьте объекты данных в фоновый поток. Это не должно быть проблемой, потому что вы добавляете данных объектов (просмотреть модели) против visual объектов (точек); визуальные объекты должны быть добавлены в том же потоке (UI), который они создаются.

Это поможет предоставить дополнительную информацию, поскольку вы не объяснили, как визуально представлять эти объекты.Является ли коллекция привязана к ItemsControl и определяет ли она DataTemplate для визуального представления каждого объекта данных?

+0

Я немного изменил свой вопрос, спасибо. Я использовал приложенное свойство с ObservableCollection из режимов просмотра для создания экземпляров представлений. Создание и добавление просмотров в VisualStaticBlocksPropertyChanged() метод, который я включил в мой вопрос. –

+0

Я предполагаю, что мой первоначальный вопрос был немного обманчивым. Проблема заключается в методе LoadBaml(), который вызывается методом InitializeComponent() и каждый раз анализирует один и тот же файл xaml. Что касается меня, было бы логично разобрать его один раз, так как это одинаково для каждого элемента управления и использовать результат каждый раз, когда нужно создать новый пользовательский элемент управления этого типа. –