2016-08-14 6 views
0

Я хочу нарисовать номера строк слева от ListBox, очень похоже на то, что AvalonEdit делает с LineNumberMargin. Когда значение ShowLineNumbers истинно, оно создает LineNumberMargin как this.Нарисовать номер строки элементов ListBox в отдельном элементе управления

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

Мое управление работает следующим образом: у меня есть отдельный элемент ItemsControl, закрепленный слева от ListBox. Каждый элемент ItemsControl - это UIElement. DesignerLineNumberMargin является одним из элементов ItemsControl и когда установлен ItemSource ListBox, я прикрепляю ListBox к DesignerLineNumberMargin. Когда отображается DesignerLineNumberMargin, я перебираю элементы ListBox и рисую номера строк.

DesignerLineNumberMargin.cs

public interface IMetadataAware 
{ 
    void Attach(ItemsControl control); 
    void Detach(ItemsControl control); 
} 

public class DesignerLineNumberMargin : FrameworkElement, IMetadataAware 
{ 
    private ItemsControl control; 
    private Typeface typeface; 
    private double emSize; 
    private int maxLineNumberLength = 2; 

    static DesignerLineNumberMargin() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(DesignerLineNumberMargin), 
      new FrameworkPropertyMetadata(typeof(DesignerLineNumberMargin))); 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     typeface = CreateTypeface(); 
     emSize = (double)GetValue(TextBlock.FontSizeProperty); 

     var text = CreateText(new string('9', maxLineNumberLength)); 

     return new Size(text.Width, 0); 
    } 

    private FormattedText CreateText(string text) 
    { 
     return 
      new FormattedText(
      text, 
      CultureInfo.CurrentCulture, 
      FlowDirection.LeftToRight, 
      typeface, 
      emSize, 
      (Brush)GetValue(Control.ForegroundProperty)); 
    } 

    protected override void OnRender(DrawingContext drawingContext) 
    { 
     if (control == null) 
      return; 

     var renderSize = RenderSize; 
     var foreground = (Brush)GetValue(Control.ForegroundProperty); 

     for (int index = 0; index < control.Items.Count; index++) 
     { 
      var item = control.Items[index]; 
      var container = (FrameworkElement)control.ItemContainerGenerator.ContainerFromItem(item); 

      var text = CreateText((index + 1).ToString(CultureInfo.CurrentCulture)); 
      //var y = container.Height; 
      var y = RenderSize.Height/(double)control.Items.Count; 

      drawingContext.DrawText(text, new Point(renderSize.Width - text.Width, y + index)); 
     } 
    } 

    private Typeface CreateTypeface() 
    { 
     var element = this; 
     return new Typeface(
      (FontFamily)element.GetValue(TextBlock.FontFamilyProperty), 
      (FontStyle)element.GetValue(TextBlock.FontStyleProperty), 
      (FontWeight)element.GetValue(TextBlock.FontWeightProperty), 
      (FontStretch)element.GetValue(TextBlock.FontStretchProperty)); 
    } 

    public void Attach(ItemsControl control) 
    { 
     this.control = control; 

     var descriptor = TypeDescriptor.GetProperties(control)["ItemsSource"]; 
     descriptor.AddValueChanged(control, OnItemsSourceChanged); 
    } 

    private void OnItemsSourceChanged(object sender, EventArgs e) 
    { 
     if (this.control.ItemsSource is INotifyCollectionChanged) 
      (this.control.ItemsSource as INotifyCollectionChanged).CollectionChanged += CollectionChanged; 
    } 

    private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     InvalidateVisual(); 
    } 

    public void Detach(ItemsControl control) 
    { 
     if (this.control == control) 
     { 
      var descriptor = TypeDescriptor.GetProperties(control)["ItemsSource"]; 
      descriptor.RemoveValueChanged(control, OnItemsSourceChanged); 

      if (this.control.ItemsSource is INotifyCollectionChanged) 
       (this.control.ItemsSource as INotifyCollectionChanged).CollectionChanged -= CollectionChanged; 
      this.control = null; 
     } 

     InvalidateVisual(); 
    } 
} 

Проблема для меня выясняя координаты у. Когда OnRender называется я не знаю Height о ListBoxItem: Рост, ActualHeight, DesiredSize всегда 0.

enter image description here

Любые идеи?

ответ

0

Я думаю, это потому, что ваш MeasureOverride() возвращает Size только с Width, но Height установлен на ноль.

Попробуйте изменить return заявление:

return new Size(text.Width, text.Height); 

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

  • Нет связанных вопросов^_^