代码之家  ›  专栏  ›  技术社区  ›  ZombieSheep

WPF控制设计指南-时间表

  •  5
  • ZombieSheep  · 技术社区  · 15 年前

    我正在为我们的一个应用程序开发一个控件。控件将当前聚焦的一天显示为网格,X轴是一天中的时间。Y轴没有这样的比例,而是将要显示的项目分开。控件的整体外观将与甘特图非常相似,它显示了一天中各种任务的时间。要了解(非常粗略的)想法,请参见下面的ASCII(非)艺术。

    8      9     10     11     12      1      2      3      4      5      6
    -----------------------------------------------------------------------------
    |      |      |      |      |      |      |      |      |      |      |
    |      ======================      |      |      |      |      |      |
    |      |      |      ======================      |      |      |      |
    |      |      |      |      |      |      |      ========      |      |
    |      |      |      |      ===========================================
    |      |      |      |      |      |      |      |      |      |      |
    

    我设计了背景网格,使其可以调整大小,并将“当前时间”指示器实现为一条垂直的蓝线,以显示我们与任务的关系。调整控件大小后,将重新计算当前时间指示器的位置,以确保它显示正确的时间。

    我现在不确定的是如何实现代表任务项的水平条。我有一个具有开始时间、结束时间、名称和描述的任务实体,我希望控件包含这些实体的集合。我也希望这些实体来驱动显示。

    我对WPF的接触是相当有限的,但在过去,我试图可视化一组对象涉及到使用列表框和数据模板。如果能把一个集合绑定到堆栈面板或类似的东西上,这样我就可以得到这样的semothing,那就太好了。(我认为stackpannel,因为它可以为我处理垂直堆叠)

    <UserControl declarations here... >
        <UserControl.Resources>
            <ObjectDataProvider x:Key="myCollection" />
        </UserControl.Resources>
        <Grid Name="myBackgroundGrid" Margin="0,0,0,0" ... >stuff goes here to draw the background</Grid>
        <StackPanel ItemsSource="{Binding Source={StaticResource myCollection}}" />
    </UserControl>
    

    有人能告诉我,我在这里的想法是否可能,并且(希望)给我一些指导,如何实现我想做的。

    事先谢谢。

    --编辑--
    显示每个任务的“控件”不必比具有开始和结束时间的行以及任务名称的工具提示更复杂。目前,我不需要钻取到任务中去,尽管这可能会在以后发生。

    1 回复  |  直到 8 年前
        1
  •  9
  •   idursun    15 年前

    假设您的数据类是这样的:

    public class TimeLineEntry
    {
        public string Name { get; set; }
        public DateTime Start { get; set; }
        public int Index { get; set; }
        public int Duration { get; set; }
    }
    

    你可以使用 ItemsControl 以矩形布局条目。

    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="{x:Type ContentPresenter}">
                <Setter Property="Canvas.Left" Value="{Binding Path=Start, Converter={StaticResource timeToPositionConverter}}" />
                <Setter Property="Canvas.Top" Value="{Binding Path=Index, Converter={StaticResource indexToPositionConverter}}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="TimeLineEntry">
                <Rectangle  Width="{Binding Duration}" Height="10" ToolTip="{Binding Name}" Fill="Red" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    在上面的XAML代码中,itemsControl(即基类ListBox、ListView等)的面板更改为 Canvas 以便更好地定位物品。

    可以使用itemsControl.itemTemplate自定义项的显示方式。

    我已经将TimelineEntry类的Start和Index属性绑定到Canvas.Left和Canvas.Top附加的ItemContainer属性,并且我还使用值转换器将日期时间值转换为像素位置。

    值转换器的代码很简单。

    public class IndexToPositionConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is int)
            {
                return ((int)value) * 10;
            }
            return 0;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }