2016-06-28 3 views
1

Я пытаюсь проанализировать производительность моего кода и лучше понять поведение перерисовки WPF для холста, который я использую как ItemsPanel внутри ListBox. С этой целью я определил пользовательский класс MyListBoxItem, который происходит от ListBoxItem (см. Код ниже).Использование пользовательского определения ListBoxItem в ListBox для анализа производительности

К сожалению, я не могу понять, как использовать этот класс внутри ListBox. Я попытался связывание списка MyListBoxItem экземпляров в ListBox.Items в XAML, как этот Items="{Binding Path=ListBoxItemsList}", но затем я получаю ошибку свойства

«С» только для чтения и не может быть установлено из разметки.

Есть ли способ достичь этого? Или, может быть, есть другая альтернатива достижению того, что я делаю? (Т.е. анализ перерисовывать-поведения)

Определение MyListBoxItem:

public class MyListBoxItem : ListBoxItem 
{ 
    public MyListBoxItem(ObjectViewModel vm) 
    { 
     this.DataContext = vm; 
    } 

    Size? arrangeResult; 

    protected override Size MeasureOverride(Size constraint) 
    { 
     var vm = (this.DataContext as ObjectViewModel); 
     if (vm != null) 
     { 
      Debug.WriteLine("For ObjectViewModel " + vm.Name + ":"); 
     } 
     arrangeResult = null; 
     System.Console.WriteLine("MeasureOverride called for " + this.Name + "."); 
     return base.MeasureOverride(constraint); 
    } 

    protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize) 
    { 
     if (!arrangeResult.HasValue) 
     { 
      System.Console.WriteLine("ArrangeOverride called for " + this.Name + "."); 
      // Do your arrange work here 
      arrangeResult = base.ArrangeOverride(arrangeSize); 
     } 

     return arrangeResult.Value; 
    } 

    protected override void OnRender(System.Windows.Media.DrawingContext dc) 
    { 
     System.Console.WriteLine("OnRender called for " + this.Name + "."); 
     base.OnRender(dc); 
    } 
} 

ответ

3

Вы можете создать производный ListBox, который переопределяет в GetContainerForItemOverride и IsItemItsOwnContainerOverride методы возвращают пользовательские ListBoxItem:

public class MyListBoxItem : ListBoxItem 
{ 
} 

public class MyListBox : ListBox 
{ 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new MyListBoxItem(); 
    } 

    protected override bool IsItemItsOwnContainerOverride(object item) 
    { 
     return item is MyListBoxItem; 
    } 
} 
+1

Это отлично работало. Благодаря! Для получения дополнительной информации я нашел эту ссылку позже: http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/ – packoman

0

Заменить шаблон дефауна в xaml:

 <ListBox> 
      <ListBox.ItemTemplate> 
       <local:MyListBoxItem /> 
      </ListBox.ItemTemplate> 
     </ListBox> 

и удалите журнал из рендера. Я думаю, что это создаст слишком матовый спам.

+0

Это поместило бы MyListBoxItem в Содержимое каждого ListBoxItem. Контейнер элементов все равно будет ListBoxItem. – Clemens

+0

Это важно для вашей цели? – Arheus

+0

Несомненно, вопрос о том, как * заменить * контейнер элементов по умолчанию (т. Е. ListBoxItem) на пользовательский. – Clemens

Смежные вопросы