2

我目前正在研究基于 Silverlight2 的考勤登记册。我想为学生和班级创建一个随时间推移的出勤可视化,但我正在努力想出一个好的方法来做到这一点。我想象的那种东西是一个网格,纵轴是学生,横轴是日期,在学生和日期的交叉点有一个符号,表示存在或不存在。理想情况下,用于生成可视化的方法也将用于生成打印材料,但这不是必需的。(Silverlight 没有内置的打印支持,所以它必须是 SQL Server Reporting Services 或类似的。)

这是我需要显示的数据类型的 Excel 中的简单模型: 样机图

(显然具有很棒的 Silverlight 样式)

以下是我目前对如何去做的想法:

  • 带有 Canvas ItemsPanel 和数据绑定定位项的 ListBox。在某些方面这将是最好的,因为它需要最少的代码,但是我无法在 Silverlight2 中很好地做到这一点(我得到的最接近的是一个 ListBox,每个项目都有一个 Canvas,项目内容位于那)。如果有成百上千的项目都需要实例化,它可能会非常慢。
  • 具有动态列的 DataGrid。我还没有尝试过,但由于在某些情况下可能有 100 多列,这似乎不是一个好的解决方案。我再次担心大量项目的性能。
  • 服务器端图像 (PNG) 生成。这将解决打印问题,因为 Silverlight 客户端和 Reporting Services 都可以引用相同的图像,但是这会阻止 Silverlight 客户端中的任何类型的交互。图像分辨率也是打印质量的一个问题。显示数千个项目时的负载将被推送到服务器,因此客户端的速度不会受到影响,除了在服务器上生成图像的初始延迟。
  • Silverlight 自定义控件。我可以构建一个自定义控件,将文本/符号放在画布上。这实际上是一个散点图。这不会解决打印问题。由于开销较低,性能可能比 ListBox 更好,但是任何数据绑定、项目选择等都必须手动编码。
  • 使用第 3 方散点图。这可能相对简单,但取决于图表库的功能。为了打印目的,必须找到另一种解决方案。
  • SVG 或 XAML 的服务器端生成。类似于图像生成,但生成用于显示或打印的矢量数据。SVG 最适合打印和导出,尽管 XPS 文档基于 XAML,所以它可以工作。在 Silverlight 中使用 SVG 需要转换为 XAML。有离线工具可以做到这一点,但没有在 Silverlight 中转换或渲染 SVG 的功能。
  • 使用大量固定宽度的文本。我们这里有一些旧的报告,它们通过生成字符串来做这种事情,......x...oo.ox...x....然后以固定宽度的字体显示。这个解决方案让我眼花缭乱,因为它看起来像是回到了绿屏终端时代,尤其是当 Silverlight 是基于矢量的时。

基本上每条思路都引导我编写自己的功能齐全的 Silverlight/报告引擎,这远远超出了我想要做的范围。另外,我真的不想给未来的维护者留下一些糟糕的定制的 hacky 显示和报告系统。(我不想结束 TheDailyWTF!)

这就是 Silverlight 所针对的那种可视化 - 我只是无法决定将我的努力指向何处。

4

1 回答 1

4

我只能想到一个简单的两级 ItemsControl(ListBox) 解决方案。内部视觉元素可以是样式化复选框,看起来像“O”或“X”,这是我刚刚为您制作的示例。当然,您确实需要将顶部的 DateHeader 集合与复选框对齐。

替代文字 http://img339.imageshack.us/img339/8695/grid.jpg

XAML

    <UserControl.Resources>
    <DataTemplate x:Key="CellTemplate">
        <Grid Width="25" Height="25">
            <CheckBox IsChecked="{Binding IsPresent}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="RowTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="80"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <TextBlock Margin="4,0,0,0" Text="{Binding Name}" TextWrapping="Wrap"/>
            <ItemsControl ItemsSource="{Binding WorkingDays}" HorizontalAlignment="Left" VerticalAlignment="Top" ItemTemplate="{StaticResource CellTemplate}" Grid.Column="1" >
                <ItemsControl.ItemsPanel>   
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>      
                    </ItemsPanelTemplate>               
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </Grid>
    </DataTemplate>
</UserControl.Resources>
<ItemsControl x:Name="lstWorkingDaysMain" ItemsSource="{Binding}" ItemTemplate="{StaticResource RowTemplate}" >
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl> 

C#

public class Student
{
    public Student()
    {
        WorkingDays = new List<WorkingDay>();
    }

    public string Name { get; set; }
    public List<WorkingDay> WorkingDays { get; set; }
}

public class WorkingDay
{
    public bool IsPresent{get; set;}
    public DateTime Date { get; set; }
}

以及 xaml.cs 后面的代码中的测试数据填充

 List<Student> students = new List<Student>();

        Student student = new Student() { Name = "Aaaaaa" };
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,5), IsPresent=true} );
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,6), IsPresent=true} );
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,7), IsPresent=true} );
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,8), IsPresent=true} );
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,9), IsPresent=true} );
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,10), IsPresent=true} );
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,11), IsPresent=true} );
        student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,12), IsPresent=true} );
        students.Add(student);

        student = new Student() { Name = "Bbbbbb" };
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 5), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 6), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 7), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 8), IsPresent = false });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 9), IsPresent = false });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 10), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 11), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 12), IsPresent = true });
        students.Add(student);


        student = new Student() { Name = "Cccccc" };
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 5), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 6), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 7), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 8), IsPresent = false });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 9), IsPresent = false });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 10), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 11), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 12), IsPresent = false });
        students.Add(student);


        student = new Student() { Name = "Dddddd" };
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 5), IsPresent = false });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 6), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 7), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 8), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 9), IsPresent = false });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 10), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 11), IsPresent = true });
        student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 12), IsPresent = true });
        students.Add(student);

        this.DataContext = students;
于 2009-07-28T05:50:18.897 回答