我想创建一个应用程序,用户可以在其中添加带有可自定义文本的矩形。矩形内部还可以有另一个矩形。正如你在这些图片上看到的那样:
我读到了关于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();
}
这是我现在的代码。我写它只是为了检查想法是否正确。
答案 0 :(得分:-1)
好吧我不确定你是否愿意这种方法,但你实际上可以做到这一点非常简单......我想也许你可以使用blend来创建用户控件并在stackpanel中设计一个标签和一个列表框并将它们全部设置为自动调整大小。 或设计2个堆叠面板,设置1做垂直方向,另一个做横向,并在水平方向上添加文本块或其他东西。