[英]Drawing hierarchically Rectangle on WPF Canvas
我正在嘗試像下一張圖片一樣放置rectangles
藍色箭頭顯示來自child
的parent-element
。
我有一個名為Box
的類,其中有Box
的父屬性。 我將所有創建的Box放入XAML代碼中用於綁定的ObservableCollection
中。
這是Box類:
public class Box
{
public string Content { get; set; } //Content in the Box
public double X { get; set; } //For Canvas.Left propertie
public double Y { get; set; } //For Canvas.Right propertie
public double Width { get; set; }
public double Height { get; set; }
public Box Parent { get; set; }
}
但是現在我沒有正確的方法在畫布上繪制矩形,如圖所示。 我想到了創建具有不同列數的網格的想法,但是我不確定是否有可能。
最好的祝福。
如果僅出於布局目的在畫布中繪制矩形,則可以利用WPF的面板輕松得多。 要將完整的綁定與ObservableCollection結合使用,需要進行大量編碼。 因此,以下是一個簡單的示例。
箱類
public class Box
{
public int Id { get; private set; }
public int ParentId { get; private set; }
public string Content { get; private set; }
public Box(string content, int id, int parentId)
{
this.Id = id;
this.ParentId = parentId;
this.Content = content;
}
}
從StackPanel繼承的BoxPanel類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public class BoxPanel : StackPanel
{
public int Id { get; private set; }
private readonly Border topPanel;
private readonly StackPanel bottomPanel;
public BoxPanel()
{
topPanel = new Border();
bottomPanel = new StackPanel { Orientation = Orientation.Horizontal };
this.Children.Add(topPanel);
this.Children.Add(bottomPanel);
}
public BoxPanel(Box box)
: this()
{
Id = box.Id;
topPanel.Child = new TextBlock
{
Text = box.Content,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Padding = new Thickness(14),
Foreground = Brushes.White,
};
topPanel.Background = (Id % 2 == 0) ? Brushes.Gray : Brushes.DarkGray;
topPanel.BorderBrush = Brushes.Black;
topPanel.BorderThickness = new Thickness(1);
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
this.Loaded += (_, __) => AdjustBottomPanel();
this.LayoutUpdated += (_, __) => AdjustBottomPanel();
}
public IReadOnlyCollection<BoxPanel> ChildrenPanel
{
get { return bottomPanel.Children.Cast<BoxPanel>().ToArray(); }
}
public void AddChildPanel(BoxPanel child)
{
bottomPanel.Children.Add(child);
AdjustBottomPanel();
}
private void AdjustBottomPanel()
{
if (!ChildrenPanel.Any())
return;
var childWidth = Math.Max((Double.IsNaN(this.Width) ? 0 : this.Width), this.ActualWidth)
/ ChildrenPanel.Count;
foreach (var child in ChildrenPanel)
child.Width = childWidth;
}
}
MainWindow的XAML
<Window x:Class="WpfBoxPanel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="500" Height="240">
<Grid x:Name="LayoutRoot"/>
</Window>
和MainWindow后面的代碼
using System.Collections.Generic;
using System.Linq;
using System.Windows;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
boxPanelRoot = new BoxPanel();
LayoutRoot.Children.Add(boxPanelRoot);
this.Loaded += (_, __) => PopulateBoxPanel();
}
private readonly IList<Box> Boxes = new List<Box>
{
new Box("1st", 1, 0),
new Box("2nd 1", 2, 1),
new Box("2nd 2", 3, 1),
new Box("3rd 1", 4, 2),
new Box("3rd 2", 5, 2),
new Box("3rd 3", 6, 3),
new Box("4th 1", 7, 4),
new Box("4th 2", 8, 5),
new Box("4th 3", 9, 5),
new Box("4th 4", 10, 6),
new Box("4th 5", 11, 6),
};
private readonly BoxPanel boxPanelRoot;
private void PopulateBoxPanel()
{
foreach (var box in Boxes)
{
var existingPanels = boxPanelRoot.GetDescendants() // See VisualTreeHelperExtensions.GetDescendants method of WinRT Xaml Toolkit
.OfType<BoxPanel>()
.ToArray();
if (existingPanels.Any(x => x.Id == box.Id))
continue;
var parent = existingPanels.FirstOrDefault(x => x.Id == box.ParentId);
if (parent == null)
parent = boxPanelRoot;
parent.AddChildPanel(new BoxPanel(box));
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.