【问题标题】:Can I draw a grid of dots within a custom WPF canvas control?我可以在自定义 WPF 画布控件中绘制点网格吗?
【发布时间】:2016-09-07 12:55:59
【问题描述】:

我构建了一个从画布继承的自定义控件。它使用 ArrangeOverride 方法向所有子元素添加拖放功能,这包括将网格对齐到 50 像素和一些其他自定义行为,例如保持元素位置。

我真正想做的是扩展它,以便在拖动时,它会在背景中显示一个点或十字网格,以便您可以看到捕捉点的位置。

但是,我无法修改控件的模板,因为它是一个面板。我尝试将其设置为包含画布的自定义控件,并传递 IEnumerable 项目源,但要了解集合的变化变得非常棘手,而且集合随后包含模型而不是框架元素。

所以我不确定我应该走哪条路。感觉好像有一个非常简单的解决方案被我忽略了,所以我愿意接受建议!

提前致谢。

【问题讨论】:

    标签: c# wpf canvas custom-controls


    【解决方案1】:

    我曾经做过类似的事情:在 UserControl 上绘制网格线,然后在其上添加控件。这是一个简单的调度程序应用程序,用于分配谁将在当月工作什么班次。我必须有列标题(天)和行标题(人)和一个可滚动的网格,我可以在其中添加/删除控件。我不知道我的解决方案能在多大程度上帮助您,但就是这样。

    我使用来自hereHeaderedScrollViewerUCHeader 是一个 UserControl,带有旋转的带有日期的文本框。奇迹发生在UC_GridLines

    <Grid>
        <lib:HeaderedScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="AliceBlue">
        <lib:HeaderedScrollViewer.TopHeader>
            <lib:UCHeader Name="ucHeader"/>
        </lib:HeaderedScrollViewer.TopHeader>
        <lib:HeaderedScrollViewer.LeftHeader>
            <Border BorderBrush="Black" BorderThickness="1,2,1,1">
                <StackPanel Orientation="Vertical"  Name="spRows" />
            </Border>
        </lib:HeaderedScrollViewer.LeftHeader>
        <Grid Name="gridContentAll">
            <Border Canvas.ZIndex="1"  Background="Transparent"
                BorderThickness="1,1,1,2" BorderBrush="Transparent">
                    <Grid ClipToBounds="True" Name="gridContent"  Background="Transparent" />
            </Border>
            <Border Canvas.ZIndex="0" BorderThickness="1,1,1,2" BorderBrush="Black" Background="White">
                <lib:UC_GridLines Name="ucGridLines" BorderThickness="0"/>
            </Border>
        </Grid>
    </lib:HeaderedScrollViewer>
    </Grid>
    

    重要的是:

    • 为包含子控件的控件设置Background="Transparent"
    • 正确设置 ZIndex,使控件显示在网格上。
    • 在根元素(例如窗口)上设置 SnapsToDevicePixels="True"UseLayoutRounding="True"

    .xaml 文件中的 UC_GridLines 没有任何内容(只有 &lt;Grid&gt;&lt;/Grid&gt;)。绘制网格线发生在代码隐藏中:

        protected override void OnRender(DrawingContext drawingContext)
        {
            // VM contains data of the grid, used to draw gridlines
            // such as number of days etc.
            if (this.VM == null)
            {
                base.OnRender(drawingContext);
                return;
            }
            double dpiFactor = 1;
            try
            {
                Matrix m = PresentationSource.FromVisual(this)
                         .CompositionTarget.TransformToDevice;
                dpiFactor = 1 / m.M11;
            }
            catch { }
    
            Pen pen = new Pen(Brushes.Black, 1 * dpiFactor);
            double halfPenWidth = pen.Thickness / 2;
    
            GuidelineSet guidelines = new GuidelineSet();
    
            double width = this.VM.Days.Count * this.VM.DayWidth - 16 * (this.VM.DayWidth / 24);
            double height = this.VM.RowHeight * rowCount;
    
            for (int i = 1; i < this.VM.Days.Count; i++)
            {
                guidelines.GuidelinesX.Add(i * this.VM.DayWidth + halfDashPenWidth);
            }
    
            for (int i = 1; i < rowCount; i++)
            {
                guidelines.GuidelinesY.Add(i * this.VM.RowHeight + halfPenWidth);
            }
    
            drawingContext.PushGuidelineSet(guidelines);
    
            for (int i = 1; i < this.VM.Days.Count; i++)
            {
                drawingContext.DrawLine(dashpen, new Point(i * this.VM.DayWidth, 0), new Point(i * this.VM.DayWidth, height));
            }
    
            for (int i = 1; i < rowCount; i++)
            {
                drawingContext.DrawLine(pen, new Point(0, i * this.VM.RowHeight), new Point(width, i * this.VM.RowHeight));
            }
    
            drawingContext.Pop();
        }
    

    【讨论】:

    • 谢谢 Arie - 这真的很有帮助。我刚刚重写了自定义控件的 OnRender 方法并添加了一个网格。知道我如何只能在用户主动拖动时显示网格吗?该渲染方法仅在最初被调用,然后在我调整控件大小时被调用。理想情况下,能够显示和隐藏它会很棒。
    • 没关系 - 呆在那里实际上很好。我已经做得很微妙了。我还必须将 base.OnRender(drawingContext) 添加到最后,否则由于某种原因,拖动/网格捕捉性能真的很差。再次感谢您提供代码示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 2017-04-14
    • 1970-01-01
    • 2013-03-08
    • 2017-04-09
    相关资源
    最近更新 更多