【问题标题】:Timelines with WPFWPF 的时间线
【发布时间】:2018-10-19 02:26:18
【问题描述】:

我正在使用DataGrid 控件开发时间线应用程序,但我找不到在单元格中插入和绑定Canvas 控件的方法。我应该使用其他控件吗?

<UserControl x:Class="Timelines.Controls.TimelineViewer2"
         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" 
         xmlns:local="clr-namespace:Timelines.Controls"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<Grid>
    <DataGrid Name="TimelineGrids" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Item" Binding="{Binding Name}"/>
            <DataGridTemplateColumn Header="Timeline" CanUserResize="True">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Canvas Name="TimelineCanvas"></Canvas>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

【问题讨论】:

  • 这里有什么问题?你的意思是你不能把Canvas放在DataGrid单元格的正确位置?请显示代码以帮助解释问题。
  • 我添加了我当前的示例代码。现在,我想添加行并访问每个“画布”以绘制时间线。
  • 但是您想从后面的代码中执行这些操作,但您无法访问画布,这是您的问题吗?
  • @Kaspar:是的,这是我的问题,但正如 kennyzx 所说,在DataGrid 单元格内访问控件似乎很困难,或者可能是不可能的。
  • @carlos,可以从后面的代码访问Canvas,见How to: Find DataTemplate-Generated Elements,但是你还有其他问题,所以我不推荐这种方式。跨度>

标签: c# wpf data-binding datagrid


【解决方案1】:

有两种绘制时间线的方法。

数据绑定与代码背后

第一个是使用数据绑定,你已经半途而废了;这样,您定义了数据模型和数据模板,模型中的条目可能具有NameBornMarried等属性, BornMarried 有一个像 1980 这样的整数值来表示年份,数据模板定义了如何条目是视觉呈现的。

另一种方法是使用后面的代码,构造Canvas 并使用C# 在Canvas... 上绘制线条、标签,然后将Canvas 插入DataGrid 单元格。

问题:

现在你卡住了,因为你希望混合它们,首先使用数据绑定从数据模型中填充DataGrid中的一些行,每一行都有一个Name标签和一个Canvas,然后您想访问Canvas 以使用后面的代码进行绘图。由于Canvas 是使用数据绑定创建的,因此您很难获得对它的引用,您甚至无法使用名称TimelineCanvas 访问它,因为该名称具有“模板范围”——这意味着它只能访问从模板内。

可以使用 VisualTreeHelper 从后面的代码访问 Canvas。请参阅如何:Find DataTemplate-Generated Elements。但我不推荐这种“混合方式”。

解决方案

坚持使用数据绑定(如果您对 XAML 感到满意)或代码隐藏。

如果你选择数据绑定,在DataTemplateinside添加行和标签,当然你需要通过绑定到模型中的一些属性来计算它们在Canvas上的位置。 p>

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Canvas Name="TimelineCanvas">
            <Label Content="Born" Canvas.X="30" Canvas.Y="20" />
            <Line
                X1="10" Y1="30"
                X2="350" Y2="30"
                Stroke="Blue"
                StrokeThickness="1" />
            <!--The whole data template can be quite complicated, but here I just hard code a label and a line to get you started-->
        </Canvas>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

如果您选择隐藏代码,请删除 CellTemplate

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Canvas Name="TimelineCanvas"></Canvas>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

在我看来,这两种方法都非常具有挑战性,您可以为Timeline 定义一个UserControl,因此可以将构造逻辑隔离在一个单独的类中。

【讨论】:

  • 对于Timeline用户控件,我应该如何从后面的代码初始化或添加事件?
  • 你定义了一个用户控件,你会得到两个自动生成的文件...这和你在MainPage.xamlMainPage.XAML.cs中做的很像,在构造函数中初始化,在XAML中添加事件...
猜你喜欢
  • 2010-12-07
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
  • 2010-09-24
  • 1970-01-01
  • 2010-12-25
相关资源
最近更新 更多