m0_58844937 2024-05-18 19:11 采纳率: 94.3%
浏览 2
已结题

窗口加载多个livechart表格,并且独立更新表格

这个是单个 livechart 表格实现效果如下:

img


遇到的问题:
① 如何把这单个表格已经实现功能了的,加载进主窗口;
② 然后由于主窗口的DataContext已经被一个单例设计的模式类占用,我该如何更新表格,如何绑定表格的数据源;
③ 由于我WPF不是很熟练,因此恳请 码友 们详细的解答一下。

img

我要把这单个的livechart表格加载到主窗口上,共5个livechart表格,并且5个表格需要可以独立更新表格的,我要实现的效果如下:

img

窗口代码如下

<Window x:Class="WpfApp_实时显示折线图.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
        xmlns:local="clr-namespace:WpfApp_实时显示折线图"
        mc:Ignorable="d"
        Title="Window2" Height="450" Width="800" Loaded="Window_Loaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" Background="AntiqueWhite">
            <Button Content="测试"  Margin="0,10,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        </Grid>
        <Grid Grid.Row="1">
            <lvc:CartesianChart Series="{Binding LineSeriesCollection}" LegendLocation="Right">
                <lvc:CartesianChart.AxisX>
                    <lvc:Axis Labels="{Binding Labels}" FontSize="14">
                        <lvc:Axis.Separator>
                            <lvc:Separator Step="1" />
                        </lvc:Axis.Separator>
                    </lvc:Axis>
                </lvc:CartesianChart.AxisX>

                <lvc:CartesianChart.AxisY>
                    <lvc:Axis LabelFormatter="{Binding CustomFormatterY}" MaxValue="{Binding AxisYMax}" MinValue="{Binding AxisYMin}" Position="LeftBottom">
                    </lvc:Axis>
                </lvc:CartesianChart.AxisY>
            </lvc:CartesianChart>
        </Grid>
    </Grid>
</Window>

窗口后台代码:

using LiveCharts;
using LiveCharts.Wpf;
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfApp_实时显示折线图
{
    /// <summary>
    /// Window2.xaml 的交互逻辑
    /// </summary>
    public partial class Window2 : Window
    {
        private Mode Modes = new Mode();
        public Window2()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = Modes;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Modes.OnClick();
        }

        public class Mode : ViewModelBase
        {
            public List<string> Labels { get; set; }
            public SeriesCollection LineSeriesCollection { get; set; }

            private double axisYMax;
            public double AxisYMax
            {
                get { return axisYMax; }
                set { axisYMax = value; this.OnPropertyChanged("AxisYMax"); }
            }
            private double axisYMin;
            public double AxisYMin
            {
                get { return axisYMin; }
                set { axisYMin = value; this.OnPropertyChanged("AxisYMin"); }
            }

            private Random Randoms = new Random();

            public Func<double, string> CustomFormatterX { get; set; }
            public Func<double, string> CustomFormatterY { get; set; }

            //绑定的X轴数据
            private ChartValues<double> ValueList { get; set; }

            private string CustomFormattersY(double val)
            {
                return string.Format("{0} mm", val);
            }

            public void OnClick()
            {
                int yValue = Randoms.Next(2, 1000);

                //向图表中添加数据
                ValueList.Add(yValue);

                //这里如果移除数组,图表曲线会原地起伏,就没有X轴移动的动画效果了
                if (ValueList.Count > 11)
                {
                    ValueList.RemoveAt(0);
                }
            }

            public Mode()
            {
                Labels = new List<string>();
                AxisYMax = 1000 + 100;
                double max = AxisYMax - 100;
                double warningMax = 750; 
                double guige = 550;
                double warningMin = 350;
                AxisYMin = 0 - 100;
                double min = AxisYMin + 100;
                ValueList = new ChartValues<double>();
                LineSeriesCollection = new SeriesCollection
                {
                    new LineSeries
                    {
                        Title = $"上限:{max} mm",
                        Values = new ChartValues<double> { max, max, max, max, max, max, max, max, max, max, max},
                        Stroke = System.Windows.Media.Brushes.Red,
                        PointGeometry = null,
                        Fill = System.Windows.Media.Brushes.LightBlue,
                    },

                    new LineSeries
                    {
                        Title = $"预警线:{warningMax} mm",
                        StrokeDashArray = new System.Windows.Media.DoubleCollection {2},
                        Values = new ChartValues<double> { warningMax, warningMax, warningMax, warningMax, warningMax, warningMax, warningMax, warningMax, warningMax, warningMax, warningMax},
                        Stroke = System.Windows.Media.Brushes.Blue,
                        PointGeometry = null,
                        Fill = System.Windows.Media.Brushes.LightBlue,
                    },

                    new LineSeries
                    {
                        Title = $"规格:{guige} mm",
                        Values = new ChartValues<double> { guige, guige, guige, guige, guige, guige, guige, guige, guige, guige, guige},
                        Stroke = System.Windows.Media.Brushes.Green,
                        PointGeometry = null,
                        Fill = System.Windows.Media.Brushes.LightBlue,
                    },

                    new LineSeries
                    {
                        Title = $"预警线:{warningMin} mm",
                        StrokeDashArray = new System.Windows.Media.DoubleCollection {2},
                        Values = new ChartValues<double> { warningMin, warningMin, warningMin, warningMin, warningMin, warningMin, warningMin, warningMin, warningMin, warningMin, warningMin},
                        Stroke = System.Windows.Media.Brushes.Blue,
                        PointGeometry = null,
                        Fill = System.Windows.Media.Brushes.LightBlue,
                    },

                    new LineSeries
                    {
                        Title = $"下限:{min} mm",
                        Values = new ChartValues<double> { min, min, min, min, min, min, min, min, min, min, min},
                        Stroke = System.Windows.Media.Brushes.Red,
                        PointGeometry = null,
                        Fill = System.Windows.Media.Brushes.LightBlue,
                    }
                };

                CustomFormatterY = CustomFormattersY;

                LineSeries lineseries = new LineSeries();
                lineseries.Title = "极耳中心距";
                //lineseries.Stroke = System.Windows.Media.Brushes.Purple;
                lineseries.DataLabels = true;
                lineseries.Values = ValueList;
                LineSeriesCollection.Add(lineseries);
            }
        }
    }
}

属性更新 类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp_实时显示折线图
{
    public class ViewModelBase
    {
        public virtual event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 属性值变化时发生
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// 属性值变化时发生
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void OnPropertyChanged<T>(System.Linq.Expressions.Expression<Func<T>> propertyExpression)
        {
            var propertyName = (propertyExpression.Body as System.Linq.Expressions.MemberExpression).Member.Name;
            this.OnPropertyChanged(propertyName);
        }
    }
}
  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-18 19:11
    关注

    引自免费微信小程序:皆我百晓生

    为了在WPF窗体上实现5个独立更新的LiveCharts图表,你需要对现有代码进行一些修改。首先,我们将创建一个新的用户控件(UserControl)来封装一个单独的图表,然后在主窗口上添加5个这样的用户控件。每个用户控件都将拥有自己的数据模型,这样它们就可以独立更新。

    1. 创建一个新的UserControl,名为CustomChartControl.xaml,并添加以下代码:
    <UserControl x:Class="WpfApp_CustomChartControl.CustomChartControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
                 mc:Ignorable="d"
                 d:DesignHeight="450" d:DesignWidth="800">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <Grid Grid.Row="0" Background="AntiqueWhite">
                <!-- 这里可以添加控制按钮或其他元素 -->
            </Grid>
            <Grid Grid.Row="1">
                <lvc:CartesianChart Series="{Binding LineSeriesCollection}" LegendLocation="Right">
                    <lvc:CartesianChart.AxisX>
                        <lvc:Axis Labels="{Binding Labels}" FontSize="14">
                            <lvc:Axis.Separator>
                                <lvc:Separator Step="1" />
                            </lvc:Axis.Separator>
                        </lvc:Axis>
                    </lvc:CartesianChart.AxisX>
    
                    <lvc:CartesianChart.AxisY>
                        <lvc:Axis LabelFormatter="{Binding CustomFormatterY}" MaxValue="{Binding AxisYMax}" MinValue="{Binding AxisYMin}" Position="LeftBottom">
                        </lvc:Axis>
                    </lvc:CartesianChart.AxisY>
                </lvc:CartesianChart>
            </Grid>
        </Grid>
    </UserControl>
    
    1. 在对应的后端文件CustomChartControl.xaml.cs中,创建一个新的数据模型类ChartMode(类似已有的Mode),并在UserControl中设置其为DataContext:
    using LiveCharts;
    using LiveCharts.Wpf;
    using System;
    using System.Collections.Generic;
    using System.Windows.Controls;
    
    namespace WpfApp_CustomChartControl
    {
        public partial class CustomChartControl : UserControl
        {
            public CustomChartControl()
            {
                InitializeComponent();
                DataContext = new ChartMode();
            }
        }
    
        public class ChartMode : ViewModelBase
        {
            // ...此处省略与原始`Mode`类相似的属性和方法
        }
    }
    
    1. 在主窗口Window2.xaml中,将现有的LiveCharts图表替换为5个CustomChartControl实例,确保它们具有不同的名称,以便区分它们的数据模型:
    <Window x:Class="WpfApp_实时显示折线图.Window2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:custom="clr-namespace:WpfApp_CustomChartControl;assembly=WpfApp_CustomChartControl"
            xmlns:local="clr-namespace:WpfApp_实时显示折线图"
            mc:Ignorable="d"
            Title="Window2" Height="450" Width="800" Loaded="Window_Loaded">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <Grid Grid.Row="0" Background="AntiqueWhite">
                <Button Content="测试" Margin="0,10,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
            </Grid>
            <Grid Grid.Row="1">
                <StackPanel Orientation="Horizontal">
                    <custom:CustomChartControl x:Name="Chart1" Margin="10"/>
                    <custom:CustomChartControl x:Name="Chart2" Margin="10"/>
                    <custom:CustomChartControl x:Name="Chart3" Margin="10"/>
                    <custom:CustomChartControl x:Name="Chart4" Margin="10"/>
                    <custom:CustomChartControl x:Name="Chart5" Margin="10"/>
                </StackPanel>
            </Grid>
        </Grid>
    </Window>
    
    1. 现在,你可以在主窗口的代码-behind中处理点击事件,通过调用不同图表的OnClick()方法来更新每个图表的数据:
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Chart1.DataContext as ChartMode)?.OnClick();
        Chart2.DataContext as ChartMode)?.OnClick();
        Chart3.DataContext as ChartMode)?.OnClick();
        Chart4.DataContext as ChartMode)?.OnClick();
        Chart5.DataContext as ChartMode)?.OnClick();
    }
    

    完成以上步骤后,你应该能在主窗口上看到5个独立更新的LiveCharts图表。每个图表都有自己的数据模型,因此它们可以独立更新。如果你想要添加额外的功能,例如控制按钮或其他UI元素,只需在CustomChartControl.xaml中添加相应的内容即可。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 5月27日
  • 已采纳回答 5月19日
  • 创建了问题 5月18日

悬赏问题

  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化
  • ¥15 Mirare PLUS 进行密钥认证?(详解)
  • ¥15 物体双站RCS和其组成阵列后的双站RCS关系验证
  • ¥20 想用ollama做一个自己的AI数据库
  • ¥15 关于qualoth编辑及缝合服装领子的问题解决方案探寻
  • ¥15 请问怎么才能复现这样的图呀