Почему использование UserControl внутри DataTemplate медленнее, чем прямой xaml?

У меня есть такой код:

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MyViewModel}">

           <!-- xaml is typed here directly -->
           <Border>
               ...
           </Border>

        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

И xaml внутри DataTemplate большой (более 200 строк).

Я хочу переместить xaml, который находится внутри DataTemplate, в отдельный UserControl, чтобы упростить его редактирование и обслуживание. делаю дальше:

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MyViewModel}">

            <!-- xaml is moved to separate UserControl -->
            <local:MyViewModelUserControl />

        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Проблема, с которой я сталкиваюсь, заключается в том, что рендеринг/обработка второго кода (с UserControl) занимает примерно в 2 раза больше времени, чем 1-й код. Есть идеи, как с этим бороться?

ПРИМЕЧАНИЕ. Я перемещаю не ListBox, а xaml, который находится внутри DataTemplate. Причина не в том, чтобы повторно использовать этот код, а в том, чтобы минимизировать основной файл, в котором находится ListBox. Другое дело, что у меня есть несколько DataTemplates внутри ListBox (для нескольких ViewModels), и xaml действительно огромен. Вот почему я хочу переместить этот xaml (который находится внутри DataTemplate) в отдельный элемент управления.


person Sergey    schedule 27.07.2016    source источник


Ответы (3)


Я знаю, что это старый вопрос, но недавно я столкнулся с этой проблемой. При создании пользовательских элементов управления в WPF возникают значительные накладные расходы, которые, по-видимому, связаны с подключением файла класса с выделенным кодом к XAML. Если все, что вы пытаетесь сделать, это переместить XAML в другое место, просто определите свой DataTemplate в ResourceDictionary в другом файле и загрузите его как StaticResource. Это даст несколько преимуществ:

(1) Возможность использовать x:Name для элементов, что не разрешено во встроенном DataTemplate.

(2) Производительность. DataTemplate с прямым XAML на несколько порядков быстрее, чем UserControl в DataTemplate.

(3) Чистота. Вы можете определить DataTemplate где угодно (словарь ресурсов в том же файле, рядом с тем местом, где вы его используете, в другом файле и т. д.) и ссылаться на него как на StaticResource.

person jam40jeff    schedule 27.04.2018

На мой взгляд, на данный момент нет необходимости выделять Listbox в отдельный UserControl, если вы используете этот ListBox только в одном месте. В любом случае, если вы так сильно озабочены оптимизацией своего кода и созданием повторно используемых элементов управления, вы можете создать отдельный файл UserControl. Но у вас не может быть модели представления для повторно используемого пользовательского элемента управления, поскольку это вещь, основанная на представлении.

Вы должны привязать необходимые свойства списка к Dependency Properties, а затем создать файл UserControl. Поступая таким образом, вы не нарушаете шаблон MVVM, а также делаете элемент управления доступным для повторного использования другими.

Задержка вызвана не тем, что вы сделали. Вероятно, это связано со временем выборки данных или каким-то другим процессом, вызывающим задержку приложения.

person ViVi    schedule 27.07.2016
comment
Я перемещаю не ListBox, а xaml, который находится внутри DataTemplate. Причина не в том, чтобы повторно использовать этот код, а в том, чтобы минимизировать его в основном файле, где находится ListBox. Другое дело, что у меня есть несколько DataTemplates внутри ListBox (для нескольких ViewModels), и xaml действительно огромен. Вот почему я хочу переместить этот xaml (который находится внутри DataTemplate) в отдельный элемент управления. Я также добавил эту информацию в ответ. Извините, если не понятно описал случай. - person Sergey; 27.07.2016
comment
Но определение шаблонов данных в отдельном файле не очень хорошо для удобства сопровождения и удобочитаемости. Список будет иметь свой собственный шаблон данных или шаблоны данных. Это не проблема. Если вы создаете повторно используемый элемент управления списком, это нормально. Но перемещение вашего шаблона данных в отдельный файл звучит не очень хорошо. - person ViVi; 27.07.2016
comment
У меня есть UserControl, который отображает элемент (некоторого ViewModel) и содержит поведение этого элемента. Я поместил этот элемент управления в ListBox.ItemTemplate. Это то, что вы можете увидеть во втором коде вопроса. И оказалось, что использование UserControl внутри ItemTemplate ListBox медленнее, чем писать тот же xaml непосредственно внутри ListBox.ItemTemplate (вы можете видеть это в 1-м коде выше). В этом проблема. - person Sergey; 28.07.2016
comment
Пожалуйста, опубликуйте код MyViewModelUserControl. Я не думаю, что проблема вызвана тем, что вы переместили код в другой xaml. Возможно, выборка данных или данные стали больше, что вызывает проблему. - person ViVi; 28.07.2016

Вы можете упростить свой "MyViewModelUserControl" - вместо наследования от UserControl вы можете наследовать непосредственно от Border и сделать это также в его XAML (Border вместо UserControl в качестве корневого элемента). Это даст вам ту же производительность, что и раньше, но вы можете сохранить ее в отдельном элементе управления.

person Martin Ch    schedule 18.10.2018