在分离的控件中绘制ListBox项的行号

时间:2016-08-14 14:19:28

标签: c# wpf listbox wpf-controls avalonedit

我想在ListBox的左侧绘制行号,与AvalonEditLineNumberMargin的行号非常相似。如果ShowLineNumbers为真,则会LineNumberMargin创建DesignerLineNumberMargin

无论如何,我看看他们是如何做到这一点并理解的,现在我正在尝试应用类似的东西,但使用ListBox(及其项目)作为绘图的来源。

我的控件的工作原理如下:我有一个独立的ItemsControl停靠在ListBox的左侧。每个ItemsControl的项目都是UIElement。 DesignerLineNumberMargin是ItemsControl的项目之一,当ListBox的ItemsSource设置时,我将ListBox附加到DesignerLineNumberMargin。当呈现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(); } } 时,我迭代ListBox的项目并绘制行号。

DesignerLineNumberMargin.cs

OnRender

我的问题是找出 y坐标。调用Height时,我不知道ListBoxItem的{​​{1}}:高度,ActualHeight,DesiredSize始终为0.

this

任何见解?

1 个答案:

答案 0 :(得分:1)

我想是的,因为您的MeasureOverride()只返回SizeWidth,但Height设为零。

尝试将return语句更改为:

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