我有Grid
表示一些数据,我需要在其上面叠加Canvas
来布局一些行。 Canvas
位于自己的UserControl
内。
问题是当Canvas
调整宽度和高度时,Grid
及其内容应自动调整。
我在Canvas
内添加了ViewBox
,但它没有做到这一点。 Grid
调整大小后,Canvas
不会调整大小。 Canvas
的目的是在网格顶部覆盖类似标尺的功能。
期待您的解决方案。
修改
我无法在网格上使用样式来替换画布,因为网格显示的信息与画布不同。可以把它想象成图表,其中有不同大小的条形列(在我的情况下是网格),天数是叠加中的线条(就像Gannt图表一样)
我的代码:
taxCanvas = new TimeAxis();
Grid.SetRowSpan(taxCanvas, GRightMain.RowDefinitions.Count);
Grid.SetColumnSpan(taxCanvas, GRightMain.ColumnDefinitions.Count);
Grid.SetColumn(taxCanvas, 0);
Grid.SetRow(taxCanvas, 0);
Grid.SetZIndex(taxCanvas, -1);
taxCanvas.Height = GRight.ActualHeight;
taxCanvas.Width = GRight.ActualWidth;
GRightMain.Children.Add(taxCanvas);
TimeAxis是我的画布用户控件,GRightMain是一个网格,它同时保存我的画布和网格,内容(Gright)位于同一行和列中。
希望这有帮助
答案 0 :(得分:4)
在我看来,画布绝对是错误的做法。
我强烈建议您查找Adorners。您可以创建自定义装饰器来完成此操作。
Adorner基本上是一个位于所有UIElements之上的“非交互式窗口”。它允许你做任何你想做的事情(创建控件,绘制东西等......),它们将出现在控件本身之上。
想象一张木制咖啡桌,上面放着一块透明玻璃。如果你在透明玻璃上画画,你仍然可以看到咖啡桌。唯一的区别是,您可以直接穿过咖啡桌上的透明玻璃并触摸木材本身。
我讨厌发布MSDN链接......但是......呃。在这种情况下,这将是一个良好的开端:
http://msdn.microsoft.com/en-us/library/ms743737.aspx
编辑:
我很快就把东西扔了。希望这有帮助吗?
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<loc:GridWithRulerxaml></loc:GridWithRulerxaml>
<Button Height="20" Width="50" >Click me</Button>
<TextBox Width="150" Height="25" HorizontalAlignment="Left">This is a text box</TextBox>
</Grid>
</Window>
用户控件:
<UserControl x:Class="WpfApplication1.GridWithRulerxaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
</Grid>
</UserControl>
USERCONTROL代码 - 背后:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for GridWithRulerxaml.xaml
/// </summary>
public partial class GridWithRulerxaml : UserControl
{
public GridWithRulerxaml()
{
InitializeComponent();
//Loaded event is necessary as Adorner is null until control is shown.
Loaded += GridWithRulerxaml_Loaded;
}
void GridWithRulerxaml_Loaded(object sender, RoutedEventArgs e)
{
var adornerLayer = AdornerLayer.GetAdornerLayer(this);
var rulerAdorner = new RulerAdorner(this);
adornerLayer.Add(rulerAdorner);
}
}
}
最后ADORNER本身:
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
namespace WpfApplication1
{
public class RulerAdorner : Adorner
{
private FrameworkElement element;
public RulerAdorner(UIElement el) : base(el)
{
element = el as FrameworkElement;
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
base.OnRender(drawingContext);
double height = element.ActualHeight;
double width = element.ActualWidth;
double linesHorizontal = height/50;
double linesVertical = width/50;
var pen = new Pen(Brushes.RoyalBlue, 2) { StartLineCap = PenLineCap.Triangle, EndLineCap = PenLineCap.Triangle };
int offset = 0;
for (int i = 0; i <= linesVertical; ++i)
{
offset = offset + 50;
drawingContext.DrawLine(pen, new Point(offset, 0), new Point(offset, height));
}
offset = 0;
for (int i = 0; i <= linesHorizontal; ++i)
{
offset = offset + 50;
drawingContext.DrawLine(pen, new Point(0, offset), new Point(width, offset));
}
}
}
}
如果您希望我详细说明代码,请告诉我。
我确认这将在主页上的任何内容上绘制一个网格。你仍然可以与下面的内容互动。
答案 1 :(得分:1)
您可以使用绑定将Canvas
的大小和Grid
的大小“绑定”到彼此。因此,当Grid
调整大小时,Canvas
会自动执行。
此外,你可以使用Converter
进行绑定,你必须计算和偏移距离边界的距离。
WPF中的绑定始终是个好主意,因此请确保您了解其工作原理。
无论如何,你总是可以在Size-Event中的代码-Beyhind(C#/ VB)中完成它。只需确定一个控件的大小并将其设置为另一个控件。就像获取Grid的 actualHeight 属性并将其设置为画布的 height 属性一样。
也许这会给你一个想法: http://blogs.msdn.com/bencon/archive/2006/05/10/594886.aspx 要么 http://www.switchonthecode.com/tutorials/wpf-tutorial-binding-converters
答案 2 :(得分:1)