2015-05-07 2 views
-3

Я хочу создать приложение, в котором пользователь может добавить прямоугольник с настраиваемым текстом внутри него. Прямоугольник также может иметь внутри. Так же, как вы можете видеть на этой картинке:Рисовать прямоугольник с текстом внутри

Example

Я читал о DrawingVisual, форме и т.д. До сих пор я сделал это с помощью DrawingVisual + хоста, который derivies от FrameworkElement. DrawingVisual имеет поле FormattedText и список элементов Children; Хост поддерживает рисование всех элементов.

Основная проблема заключается в том, что каждый раз пользователь меняет текст в любом дочернем элементе Мне нужно рассчитать новые координаты, ширину, высоту всех дочерних элементов. Возможно, есть какой-либо способ сделать это автоматически?

Кроме того, DrawingVisual не имеет событий мыши. Итак, как сделать все элементы доступными/зависящими друг от друга? Или я должен получить какой-то другой класс?

Позже я отправлю код ...

EDIT:

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(); 
    } 

Это мой код сейчас. Я написал это только для проверки правильности идеи.

+3

, пожалуйста, разместите свой код прямо сейчас. –

+0

отправил некоторый код – krzysnick

ответ

-1

ну, я не уверен, если вы хотите этот подход, но вы можете сделать это очень просто ... Я думаю, вы можете использовать blend для создания пользовательского элемента управления и создания ярлыка и списка в stackpanel и установить их все на автосоциализацию. или дизайн 2 панели стеллажей 1, чтобы сделать вертикальную ориентацию, а другую - горизонтальную и добавить текстовые блоки или что-то в горизонтальное.

+0

Спасибо за ответ, но я хочу сделать это с помощью рендеринга на холсте ... – krzysnick

+0

поэтому класть холст вместо стековой панели ... если я хочу, я могу показать вам, как создавать пользовательские элементы управления –