“Dynamically"生成一个WPF视图c#与动态数据显示绘图

本文关键字:视图 WPF 一个 动态 绘图 显示 数据 quot Dynamically | 更新日期: 2023-09-27 18:07:55

我正在用c#编写一个WPF应用程序。本应用程序是使用MVVM设计的。

目前,我有一个父窗口与几个复选框。用户可以选择他们想要的任何框,然后点击"plot"Button。一旦点击"plot",就会出现一个新的子窗口,以单个图形显示数据。

所以,如果我只选中了一个复选框,然后点击"plot",我将看到一个带有单线的图形。如果我有两个复选框,选中并点击"绘图",我将看到相同的单个图形,但它上面有两条线。

我当前的实现:

目前,我有一个名为GraphWindowView的"视图"类。视图显然需要知道要显示哪些数据。因此,为了做到这一点,我有依赖属性GraphWindowView.DatesGraphWindowView.Data,最终产生Data (y轴)与Dates (x轴)的图形。

问题: GraphWindowView的当前实现显然仅限于能够绘制一组数据(即DataDates)。我想使这个(很多)更可扩展,并有一个任意数量的绘图可用取决于多少复选框被选中。我该怎么做呢?我想我需要重新考虑我对依赖属性的使用…

>>>更新

所以我做了一个GraphLine类,它应该代表图形上的一条线。"图形"实际上是GraphWindowPresenter.xaml类中的ChartPlotter元素。此外,我为GraphLine对象指定了DataType,但这就是我所理解的。接下来的步骤是什么,如何将数据添加到图中?我如何/在哪里使GraphLine的实例填充ChartPlotter元素?抱歉,即使在阅读了相当多的教程之后,我对这一点还是很迷茫。感谢到目前为止所有的帮助,我真的很感激!

GraphWindowView.xaml

<Window x:Class="BMSVM_Simulator.View.GraphWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModel="clr-namespace:BMSVM_Simulator.ViewModel"
        xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
        x:Name="ThisGraphWindowInstance"
        Title="Plot" Height="500" Width="750"
        Icon="../res/qualcomm_q_icon.ico.ico"
        MinWidth="400" MinHeight="300">
    <Window.DataContext>
        <ViewModel:GraphWindowPresenter/>
    </Window.DataContext>
    <d3:ChartPlotter Name="plotter" Margin="10,10,20,10">
        <d3:ChartPlotter.HorizontalAxis>
            <d3:HorizontalIntegerAxis Name="dateAxis"/>
        </d3:ChartPlotter.HorizontalAxis>
        <d3:ChartPlotter.VerticalAxis>
            <d3:VerticalIntegerAxis Name="countAxis"/>
        </d3:ChartPlotter.VerticalAxis>
        <d3:Header FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=title}"/>
        <d3:VerticalAxisTitle FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=yAxis}"/>
        <d3:HorizontalAxisTitle FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=xAxis}"/>
    </d3:ChartPlotter>
    <Window.Resources>
        <DataTemplate DataType="{x:Type ViewModel:GraphLine}">
            <!--WHAT GOES HERE-->
        </DataTemplate>
    </Window.Resources>
</Window>

GraphLine.cs

namespace BMSVM_Simulator.ViewModel
    {
        class GraphLine
        {
            public string xAxis                     { get; private set; }
            public string yAxis                     { get; private set; }
            public string title                     { get; private set; }
            public string legend                    { get; private set; }
            public EnumerableDataSource<int> data   { get; private set; }
            public EnumerableDataSource<int> dates  { get; private set; }
        }
    }

“Dynamically"生成一个WPF视图c#与动态数据显示绘图

WPF中的大多数此类问题都可以通过仔细使用数据绑定和DataTemplate来解决,而不是使用大量的过程代码。一般的想法是,您创建一个自定义类,其中包含绘制所有线条所需的所有属性。然后,您将声明一个DataTemplate来定义如何将各种属性绑定到数据上,可能像这样:

<DataTemplate DataType="{x:Type YourXamlNamespacePrefix:GraphLine}">
    <Line X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" />
</DataTemplate>

然后创建一个自定义类实例的集合,并将其数据绑定到一些集合控件,如ItemsControl,每个集合将自动呈现在正确的位置:

<ItemsControl ItemsSource="{Binding YourGraphLineCollection, RelativeSource={
    RelativeSource AncestorType={x:Type YourXamlNamespacePrefix:YourControlName}}}" />

欢迎来到WPF数据绑定和DataTemplate的强大世界。


更新>>>

数据绑定到Line元素的自定义类不是视图模型。可以把它看作一个数据类型类,您将像上面那样为它声明一个DataTemplate。当我说它应该具有所有必需的属性时,如果您查看上面的示例,就会发现它至少需要四个double属性来数据绑定到Line元素的四个已使用的属性。但是,您也可以选择向数据绑定添加更多属性,例如StrokeStrokeThicknessFill属性。

至于应该在哪里定义DataTemplate,它应该在应用它的项的范围内。如果您想在一个视图中使用它,那么将它放在该视图的UserControl.Resources部分中。但是,如果您想使用相同的DataTemplate,那么您应该将其放入App.xaml文件的Application.Resources部分,因为这些Resources在应用程序范围内可用。


FINAL UPDATE>>

正如我在评论中提到的,教用户如何使用WPF绝对超出了这个网站的范围,所以我不会这样做。要了解DataTemplate s,您应该阅读MSDN上的数据模板概述页面。当你不知道一些事情的时候,MSDN应该总是是你搜索答案的第一个地方。

在我离开之前,我可以给你一些最后的提示:控件中的DependencyProperty应该是ObservableCollection<GraphLine>类型。在控件内部,您应该将它们数据绑定到某种ItemsControl,如上所示-我更改了其中的Binding Path,因为您应该真正使用RelativeSource Binding来定位您的情况下的属性(其中YourControlName是您想要绘制Line对象的UserControl的名称)。

最后,在视图模型中(与包含新UserControl的视图链接),您将需要一个集合属性来与UserControl中的集合进行数据绑定,比如命名为YourGraphLineCollectionInViewModel:

<YourXamlNamespacePrefix:YourControlName YourGraphLineCollection="{Binding 
    YourGraphLineCollectionInViewModel}" />

在这个视图模型中,您将GraphLine类的实例添加到YourGraphLineCollectionInViewModel集合中,只要您已经设置了Binding Path,它们就会出现在ItemsControl的UI中。我假设你知道如何正确设置你的DataContext -如果不知道,你可以很容易地在网上找到如何做到这一点。