繁体   English   中英

在单独的控件中绘制ListBox项的行号

[英]Draw line number of ListBox items in a separated control

我想在ListBox的左侧绘制行号,这与AvalonEditLineNumberMargin所做的非常相似。 ShowLineNumbers为true时,它将像这样创建LineNumberMargin

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

我的控件是这样的:我有一个单独的ItemsControl停靠在ListBox的左侧。 每个ItemsControl的项目都是一个UIElement。 DesignerLineNumberMargin是ItemsControl的项目之一,当设置了ListBox的ItemsSource时,我将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();
    }
}

我的问题是弄清楚y坐标 调用OnRender ,我不知道ListBoxItemHeight :Height,ActualHeight,DesiredSize始终为0。

在此处输入图片说明

有什么见解吗?

我猜这是因为您的MeasureOverride()返回的Size只有Width ,而Height设置为零。

尝试将return语句更改为:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM