ItemsControl条形图缩放条形图

时间:2012-04-18 14:10:02

标签: c# wpf charts itemscontrol

编辑:添加代码

此外,由于DateTimes不是真正的Datetimes(shrings in hh:mm:ss format),我决定只使用Strings并使用TimeSpan来检索totalMinutes。

<ObjectDataProvider x:Key="odpLbGrafiek" ObjectType="{x:Type myClasses:GrafiekBar}" MethodName="GetDataGrafiek"/>

    <DataTemplate x:Key="GrafiekItemTemplate">
        <Border Width="Auto" Height="Auto">
            <Grid>
                <Rectangle StrokeThickness="0" Height="30"  
                           Margin="15" 
                           HorizontalAlignment="Right" 
                           VerticalAlignment="Bottom"
                           Width="{Binding Value}"
                           Fill="{Binding Fill}">
                    <Rectangle.LayoutTransform>
                        <ScaleTransform ScaleX="20" />
                    </Rectangle.LayoutTransform>
                </Rectangle>
            </Grid>
        </Border>
    </DataTemplate>

“填充”实际上给出了条形图栏上的大小。

itemsControl:

<ItemsControl x:Name="icGrafiek"  
            Margin="20,3,0,0" 
            ItemsSource="{Binding Source={StaticResource odpLbGrafiek}}"
            ItemTemplate="{DynamicResource GrafiekItemTemplate}" 
            RenderTransformOrigin="1,0.5" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.RowSpan="6">
            <ItemsControl.RenderTransform>
                <TransformGroup>
                    <ScaleTransform ScaleY="-1" ScaleX="1"/>
                    <SkewTransform AngleY="0" AngleX="0"/>
                    <RotateTransform Angle="180"/>
                    <TranslateTransform/>
                </TransformGroup>
            </ItemsControl.RenderTransform>
        </ItemsControl>

在数据绑定中调用以下方法。 bar.Value给出了datatemplate中宽度值的值,该值给出了条形的大小。

    public ObservableCollection<GrafiekBar> GetDataGrafiek()
    {
        var converter = new System.Windows.Media.BrushConverter();

        Double maxValueStilstanden = GetLargestValueStilstanden();

        TimeSpan tsMaxValue = TimeSpan.Parse(maxValueStilstanden.ToString());
        totalMinutesMaxValue = tsMaxValue.TotalMinutes; 

        //calculate % of stilstanden Values
        foreach(String t in stilStandenList)
        {
            TimeSpan ts = TimeSpan.Parse(t);
            Double totalMin = ts.TotalMinutes;

            totalMin = totalMin / totalMinutesMaxValue * 100;

            valuesChartPercentage.Add(totalMin);
        }

        for (int j = 0; j < valuesChartPercentage.Count; j++)
        {
            GrafiekBar bar = new GrafiekBar();
            bar.Value = valuesChartPercentage[j];
            bar.Fill = converter.ConvertFromString(kleuren[j]) as Brush;
            listGrafiek.Add(bar);
        }

        return listGrafiek;
    }

另一个问题实际上是宽度(条的大小)。我实际上必须做* 10000来获得酒吧本身的任何视觉效果。


我正在使用样式的 ItemsControl ,因此它看起来像条形图。

因此,例如,具有从1到5的5个值的数组创建具有不同条形尺寸的5个条形,并且每个条形具有不同的颜色。 与以下示例http://www.c-sharpcorner.com/uploadfile/mahesh/bar-chart-in-wpf/

大致相同

问题:

我的问题在于条形的缩放大小(在这种情况下为width属性,因此需要int / double值)。

  • 我的程序以HH:mm:ss格式记录几个DateTimes
  • 应在这些日期时间缩放条形

例如,我可以有一个01:22:11的栏或00:01:11的栏,最多可达6个。

将这些DateTime值缩放到某个double值的最佳方法是什么? 该值将用于给出图表上条形的大小。

猜猜我正在寻找某种计算方法来计算我的所有值,所以我不会突然得到一个非常大的值并且超出我的UI。

最干净的解决方案是将所有条形图彼此进行比较,当一个条形图发生变化时,另一个条形图会增大/缩小,但这并不是必需的,尽管它不像听起来那么复杂。

条形码本身并不需要过于精确,它只能用于了解情况的一般情况。确切的值将写入数据库。

欢迎任何建议!

谢谢PeterP。

4 个答案:

答案 0 :(得分:1)

归一化。

  • 将总时间转换为秒。
  • (将总可用宽度除以总时间)= factorA
  • 找到每个条的适当宽度,将其时间乘以factorA

编辑:选择合适的日期/时间来测量零,或者你可以使用你的DateTime对象的总秒数属性

答案 1 :(得分:1)

我会选择一个基准日期,并使您的收集图表显示基准日期和数据日期之间的天数/小时/分钟

您甚至可以使用转换器执行此操作,您可以将基准日期作为转换器参数传递。

您的两个示例日期(01:22:1100:01:11)实际上是时间,所以在这种情况下,我只是绘制了自0以来的分钟数,因此您的实际数据值将会显示为是82和1

为了回应您关于缩放的编辑问题,您将以百分比形式绘制所有内容。在这种情况下,请根据最大数字的百分比取最大数字并绘制每隔一个数字的图表。

因此,使用您的两个示例时间,我将它们转换为数字82和1,将较大的数字(82)转换为100%,并返回包含每个数字的百分比的列表为82,因此返回列表将包含100%和1.2%(1/82)。

您仍然可以在ViewModelItemsSource转换器中执行此操作(转换器会将整个列表作为参数,并返回整个返回值列表)


修改

在回复下面的评论时,我将使用Converter上的ItemsSource进行设置。转换器只需获取一个数据值,并将其转换为另一个特定于显示UI的值。

最初的XAML看起来像这样:

<ItemsControl ItemsSource="{Binding MyCollection, 
    Converter="{StaticResource MyTimeConverter}}" />

其中MyCollectionObservableCollection<DateTime>MyTimeConverter执行以下操作:

  1. 将传递的value投放为ObservableCollection<DateTime>,因为所有转换器参数都以object传递
  2. 循环收集并找出最长的时间
  3. 花费集合中最大的时间,并计算它有多少分钟。这将是您基于所有其他时间的100%价值,因此存储您的最大时间在变量中的分钟数
  4. 为返回值
  5. 创建新的List<decimal>
  6. 循环开始收集。对于集合中的每一次,将其除以&#34; 100%值&#34;您在步骤3中存储的内容,它将为您提供该条与最大值进行比较的百分比。将此百分比添加到返回List<decimal>
  7. List<decimal>返回ItemsControl。此List<decimal>将用作ItemsSource,而不是实际的ObservableCollection<DateTime>
  8. 这意味着您的ItemsControl现在绑定到一组小数,其中一个值为100%,将占据屏幕的整个宽度,所有其他值都缩放到最大值。

    关于使用计时器更新集合的问题,您的计时器应更新ObservableCollection<DateTime>绑定的MyCollection ItemsControl。定时器根本不应该知道或关心转换器代码。

    例如,如果您的计时器想要用一整套新的时间重新创建MyCollection,那么它可以,并且UI将自动重新运行转换器代码并更新条形图,因为{{ 1}}将在集合发生变化并且UI需要更新时告诉UI。

    至于&#34;基准日期&#34;我在下面的评论中指的是,如果你要绘制一组日期而不是时间,你会想要一个基线日期,这样你的图形就不会延伸到ObservableCollections。您不想使用最小日期,因为这会导致您的条形图中显示为最低值,因此您可以将1/1/0001特定日期作为起点用于图形。如果基准日期是1/1/12并且您的最大日期是3/1/12,那么您的图表将从1/1/12延伸到3/1/12。

    基准日期将用于转换器的步骤3和5。例如,您可以获得基准日期和数据日期之间的天数,而不是获得当时的分钟数。

    您还可以计算转换器中的基准日期,例如最低日期之前的10天,但这可能会使图表偏差超出您的喜好,具体取决于数据。

答案 2 :(得分:0)

听起来你只需跟踪所有值的最大值。然后,根据此最大值缩放每个值:

var scale = value / maximum;
var height = scale * ActualHeight;

当然,实际设置每个项目高度的方式可能是通过绑定。

答案 3 :(得分:0)

imho你的整个条形图应该在后面有一个ViewModel,这个VM有逻辑来计算最大值,然后定义缩放。