用里面的文字画出矩形

时间:2015-05-07 15:25:20

标签: c# wpf shape

我想创建一个应用程序,用户可以在其中添加带有可自定义文本的矩形。矩形内部还可以有另一个矩形。正如你在这些图片上看到的那样:

Example

我读到了关于DrawingVisual,Shapes等的内容。到目前为止,我使用的是DrawingVisual + Host,它是从FrameworkElement派生的。 DrawingVisual具有FormattedText字段和Children元素列表;主持人维护绘制所有元素。

主要问题是,每当用户更改任何子元素中的文本时,我需要计算所有子元素的新坐标,宽度和高度。 也许有任何方法可以自动执行此操作?

此外,DrawingVisual没有任何鼠标事件。那么如何使所有元素可选择/可以进行?或者我应该从其他课程派生出来?

稍后我会发布一些代码......

修改

public class VisualHost: FrameworkElement
{
    private VisualCollection _children;
    private List<MyElement> _list;

    public VisualHost(List<MyElement> list)
    {
        _children = new VisualCollection(this);
        _list = list;
    }

    protected override int VisualChildrenCount
    {
        get { return _children.Count; }
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= _children.Count)
        {
            throw new ArgumentOutOfRangeException();
        }

        return _children[index];
    }

    private void CheckSize(MyElement element)
    {
        double sw = 0;
        double mh = 0;
        if (element.GetChildCount() > 0)
        {
            for (int i = 0; i < element.GetChildCount(); i++)
            {
                CheckSize(element.GetChild(i));
                sw += element.GetChild(i).Width;
                mh = Math.Max(mh, element.GetChild(i).Height);
            }
        }
        element.Width = Math.Max(element.Formatted.Width, sw);
        element.Height = element.Formatted.Height + mh;
    }

    private void DrawElement(double top, double left, MyElement element)
    {
        CheckSize(element);

        var context = element.RenderOpen();
        context.DrawRectangle( null, new Pen(Brushes.Black, 2d), new Rect(new Point(left, top), new Size(element.Width, element.Height)));
        context.DrawText(element.Formatted, new Point(left, top));

        top += element.Formatted.Height;
        if (element.GetChildCount() > 0)
        {
            for (int i = 0; i < element.GetChildCount(); i++)
            {
                context.DrawRectangle(null, new Pen(Brushes.Black, 2d), new Rect(new Point(left, top), new Size(element.GetChild(i).Width, element.GetChild(i).Height)));
                context.DrawText(element.GetChild(i).Formatted, new  Point(left, top));
                left += element.GetChild(i).Width;
            }
        }
        context.Close();
        _children.Add(element);
    }

    public void Redraw()
    {
        if (_list != null)
        {
            double top = 0, left = 0;
            foreach (MyElement element in _list)
            {
                DrawElement(top, left, element);
                top += element.Height + 10d;
            }
        }
    }
}



public class MyElement: DrawingVisual
{
    private string _text;

    public string Text 
    {
        get { return _text; } 
        set {
            if (_text != value)
            {
                Typeface typeface = new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
                Formatted = new FormattedText(value, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12, Brushes.Red);

                _text = value;
            }
        }
    }

    public FormattedText Formatted { get; private set; }
    public double Height { get; set; }
    public double Width { get; set; }

    private List<MyElement> _children;

    public MyElement GetChild(int i)
    {
        if (i < 0 || i >= _children.Count)
        {
            throw new ArgumentOutOfRangeException();
        }
        return _children[i];
    }

    public int GetChildCount()
    {
        return _children.Count;
    }

    public void AddChild(MyElement child)
    {
        _children.Add(child);
    }

    public MyElement(string Text)
    {
        this.Text = Text;
        this._children = new List<MyElement>();
    }

}

MainWindow.xaml.cs

public MainWindow()
    {
        InitializeComponent();
        _list = new List<MyElement>();
        _list.Add(new MyElement("text"));

        var e = new MyElement("text 2");
        e.AddChild(new MyElement("a"));
        e.AddChild(new MyElement("b"));
        e.AddChild(new MyElement("c"));

        _list.Add(e);

        _host = new VisualHost(_list);
        MyCanvas.Children.Add(_host);
        _host.Redraw();
    }

这是我现在的代码。我写它只是为了检查想法是否正确。

1 个答案:

答案 0 :(得分:-1)

好吧我不确定你是否愿意这种方法,但你实际上可以做到这一点非常简单......我想也许你可以使用blend来创建用户控件并在stackpanel中设计一个标签和一个列表框并将它们全部设置为自动调整大小。 或设计2个堆叠面板,设置1做垂直方向,另一个做横向,并在水平方向上添加文本块或其他东西。