• 使用ListBox控件来实现直方图控件(二)


    前一篇文章里面讲到了实现一个直方图控件所要注意的问题,既然是一个控件,那么需要先将给用户调用的API调用出来。如果读者有使用Office Excel的经验的话,就会发现,制作一个直方图,实际上只需要显示直方图的数据就可以了,如下图所示:



    上图,再分解一下,可以看到每一个
    Series是一个系列的数据(比如一个数组);而每一个Category可以看成是用来识别一个数据的标识(例如数组的下标);当然最后剩下的就是数据啦。因此直方图控件给用户的定义的使用方法应该是:

    Xaml代码:

    <Window x:Class="CodeLibrary.Test.Window1"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:local="clr-namespace:CodeLibrary.Charts"

        Loaded="Window_Loaded" Title="Window1" Height="600" Width="800">

     <local:Histogram x:Name="TestHistogram"

                       Width="8000"/>

    </Window>

    C#代码:

    private void Window_Loaded(object sender, RoutedEventArgs e)

    {

        double[] test = new double[256];

        double[] test2 = new double[256];

        Random random = new Random(1000);

        for (int i = 0; i < test.Length; ++i)

        {

            test[i] = random.Next();

            test2[i] = random.Next();

        }

     

    TestHistogram.HistogramData = test;

    TestHistogram.AddHistogramData(test2, "Series 2");

    }

     

    这样一来,控件的最基本的API已经定义完毕,至于直方图其它的属性,可以等到整个直方图完善了以后再慢慢添加进去。对比WPF的控件实现方式,使用UserControl会比从已有的一个控件继承下来更方便一些,因为编辑UserControlXaml会相对直观一些。在写代码之前,先讲一下思路,为什么可以使用ItemsControl(ListBox是从ItemsControl继承下来的)来绘制一个直方图,先看看一个最普通的ItemsControl的代码:


    默认情况,
    ListBox是以垂直排列的方式来排列每一个列表项的,而ListBox中的ItemsPanel属性允许你替换掉默认的排列列表项的面板,ListBox使用的默认面板是VirtualizingStackPanel,在数据绑定的情况下,VirtualizingStackPanel这个面板只会从绑定的数据里面创建在电脑屏幕中显示的列表项,这样最大程度优化了界面的性能好东西。默认情况下,VirtualizingStackPanel是垂直排列放在里面的控件的这就是为什么ListBox是垂直排列列表项的原因。

    那么现在尝试一下将ListBox默认的排列行为改成横向排列,请看下图:


    上面的代码,将
    VirtualizingStackPanel的布局方式从垂直排版改到水平排版,ListBox的列表项的布局方式也改变了。有了这个基础以后,我们来看如何实现直方图,其实我们可以把直方图看成一个大“竹简”,“竹简”里面的每一块显示直方图 里面的一个矩形和X轴上面的刻度,Y轴我们先不考虑,因此直方图可以以类似下面的角度来看:


    这样一来,借助重载
    ItemsControlItemTemplateItemsPanel属性,比如下面的代码可以得到一个最简单的直方图的式样了:

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

          xmlns:system="clr-namespace:System;assembly=mscorlib"

          xmlns:collection="clr-namespace:System.Collections;assembly=mscorlib">

     <Page.Resources>

        <ObjectDataProvider MethodName="GetValues"

                             ObjectType="{x:Type sys:Enum}"

                             x:Key="data">

          <ObjectDataProvider.MethodParameters>

            <x:Type TypeName="HorizontalAlignment" />

          </ObjectDataProvider.MethodParameters>

        </ObjectDataProvider>

     

     </Page.Resources>

     <ListBox ItemsSource="{Binding Source={StaticResource data}}">

        <ListBox.ItemsPanel>

          <ItemsPanelTemplate>

            <VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />

          </ItemsPanelTemplate>

        </ListBox.ItemsPanel>

        <ListBox.ItemTemplate>

          <DataTemplate>

            <Grid Width="50">

              <Grid.RowDefinitions>

                <RowDefinition Height="*" />

                <RowDefinition Height="20" />

              </Grid.RowDefinitions>

              <Rectangle Grid.Row="0" Fill="Gray" Height="100" />

              <Label HorizontalAlignment="Center" Content="{Binding}" Padding="0" Margin="0" Grid.Row="1" />

            </Grid>

          </DataTemplate>

        </ListBox.ItemTemplate>

     </ListBox>

    </Page>

     

    下图就是最终得到的效果:


    好了,接下来的问题就是如何把前面
    Xaml里面硬编码的数据用实际程序中变化的数据代替,未完待续……

  • 相关阅读:
    图解ArrayList源码
    HashMap相关
    1. 两数之和
    判定字符是否唯一
    反射相关
    自定义注解
    TreeMap相关
    判定是否互为字符重排
    2. 两数相加
    线程基础
  • 原文地址:https://www.cnblogs.com/killmyday/p/1528758.html
Copyright © 2020-2023  润新知