电子大屏
nuget包
1.LiveChartsCore.SkiaSharpView.WPF
基于 LiveChartsCore 和 SkiaSharp 构建。它可以帮助开发者在 WPF 应用程序中创建漂亮、交互式的图表,支持多种类型的图表和丰富的自定义选项。
1-安装LiveChartsCore.SkiaSharpView.WPF包 2-在xaml中添加
xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF"2.CommunityToolkit.Mvvm
由 .NET Community Toolkit 提供的 NuGet 包,它专为 .NET 应用程序(尤其是 WPF、WinUI、Xamarin 等)提供了一个轻量级的 MVVM(Model-View-ViewModel)实现工具集。
1-安装CommunityToolkit.Mvvm包 2-添加ObservableProperty 特性,简化属性通知机制,避免了手动实现 INotifyPropertyChanged
ObservableProperty 是 CommunityToolkit.Mvvm 提供的特性,它会自动为属性实现 INotifyPropertyChanged 接口。这意味着,当这些属性的值发生变化时,UI 会自动更新。
字段通常是小驼峰命名法(例如 _data 或 _myData),比如,字段 _data 会生成一个公开属性 Data。
窗口大小
WindowState="Maximized" 该属性用于控制窗口的状态。WindowState 可以有以下几种值:
Normal:常规大小 Maximized:窗口被最大化到屏幕的最大大小。 Minimized:窗口被最小化。
提高显示的清晰度和准确度
SnapsToDevicePixels="True"控制窗口或元素的绘制精度的属性。当设置为 True 时,WPF 会确保控件的边界和像素点对齐,以避免出现模糊的效果,特别是在高分辨率显示器或高DPI环境中。
控制图像适应容器
<Image Grid.ColumnSpan="3" Grid.RowSpan="3" Source="/图片/上下框.png" Stretch="Fill" />Grid.ColumnSpan="3" Grid.RowSpan="3" 图片会占用 3 列和 3 行的空间。
stretch 属性控制图像如何适应其容器的大小。
None:图片保持原始大小,不进行缩放。
Uniform:图片保持纵横比进行缩放,直到图片的长边与容器对齐。
UniformToFill:图片保持纵横比缩放,直到图片的短边与容器对齐,可能会裁剪图片的部分。
Fill:图片会拉伸以填充整个容器,可能会失去纵横比,图片会被拉伸或压缩以适应容器。
TextBlock 设置
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding 实时信息.当前时间, StringFormat=\{0:yyyy-MM-dd HH:mm:ss\}}" FontSize="20" Foreground="Black"/>渐变色背景
RadialGradientBrush 作为背景,GradientOrigin:指定渐变的起点。Center:指定渐变的中心点。在这里,0.5, 0 表示渐变从窗口顶部的中间开始。RadiusX 和 RadiusY:控制渐变的扩展范围。RadiusX 和 RadiusY 的值控制渐变的水平和垂直范围,值 0.7 表示渐变将从中心向外扩展 70%。
GradientStop:定义渐变中的颜色和其位置。第一个 GradientStop 颜色位于渐变的起始位置,第二个 GradientStop 颜色位于渐变的终点位置。
<Window.Background>
<RadialGradientBrush GradientOrigin="0.5,-0.8" Center="0.5,0" RadiusY="0.7" RadiusX="0.7">
<GradientStop Color="#A02B40" Offset="0"/>
<GradientStop Color="#08113c" Offset="1"/>
</RadialGradientBrush>
</Window.Background>使用 INotifyPropertyChanged 和 Task.Delay 实现异步刷新
private async Task 每秒更新时间()
{
while (true)
{
await Task.Delay(1000);// 每1秒钟等待
实时信息.当前时间 = DateTime.Now;// 更新当前时间
}
}*DispatcherTimer** 是最简单的方法,可以直接在主线程上定时执行任务。
Task.Delay 配合异步方法可以避免使用定时器,适合处理延时任务。
BackgroundWorker 和 Thread 方法适用于需要在后台线程中执行较复杂任务时。
System.Timers.Timer 适合简单的定时任务,但需要使用 Dispatcher.Invoke 来更新 UI。
Grid.Row="1"在父 Grid 中的第二行
Grid.Row="1" 表示该控件位于第二行。如果没有父 Grid,则这行代码会抛出错误,因为 Grid.Row 只能在父 Grid 中使用。
自定义控件UserControl
<local:外框 Margin="10"/>
//外框
public partial class 外框 : UserControl
{
public 外框()
{
InitializeComponent();
}
}
<UserControl x:Class="电子大屏.外框"/>Border绘制矩形
<Border BorderThickness="1" BorderBrush="#02a6b5" Grid.RowSpan="2" Background="#101f51" Opacity="0.1"></Border>
<Border BorderThickness="1" Grid.Row="0" Grid.Column="2" Margin="10" Background="#C0FFFFFF" CornerRadius="10" BorderBrush="Black" Opacity="0.2" Grid.RowSpan="2">
<Border.Effect>
<DropShadowEffect ShadowDepth="5" BlurRadius="10" Color="Black" Opacity="0.5"/>
</Border.Effect>
</Border>BorderThickness="1" 设置边框的宽度为 1。BorderBrush="#02a6b5" 设置边框的颜色为 #02a6b5
Grid.RowSpan="2" 表示该 Border 会跨越 2 行,覆盖两行的区域。Background="#101f51" 设置背景颜色为深蓝色。Opacity="0.1" 设置透明度为 10%
CornerRadius="10"设置 Border 的圆角半径为 10.
DropShadowEffect 为 Border 添加了阴影效果:
ShadowDepth="5":阴影的深度,表示阴影偏移的距离。
BlurRadius="10":阴影的模糊半径,值越大阴影越模糊。
Color="Black":阴影的颜色为黑色。
Opacity="0.5":阴影的透明度为 50%,即阴影有一半的透明度,显得更加柔和。
Line绘制边框
<Line X1="0" Y1="0" X2="0" Y2="10" StrokeThickness="2" Stroke="#02a6b5" HorizontalAlignment="Right" VerticalAlignment="Bottom"></Line>X1 和 Y1 作为起始点坐标,X2 和 Y2 作为终止点坐标。StrokeThickness="2" 设置线条的粗细为 2。
Stroke="#02a6b5" 设置线条的颜色为 #02a6b5 HorizontalAlignment 和 VerticalAlignment相对于父元素的对齐方式来定滴
DataGrid绑定数据源
<DataGrid x:Name="表格_工序合格率显示" ItemsSource="{Binding 工序合格率显示}" FontSize="23" Margin="15" Background="Transparent" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="#" Binding="{Binding 序号}"/>
<DataGridTextColumn Header="工位" Binding="{Binding 工位}"/>
<DataGridTextColumn Header="加工总数" Binding="{Binding 测试总数}"/>
<DataGridTextColumn Header="合格数" Binding="{Binding 合格数}"/>
<DataGridTextColumn Header="合格率" Binding="{Binding 合格率}"/>
</DataGrid.Columns>
</DataGrid>背景为透明,外边距为 15,并且没有自动生成列(AutoGenerateColumns="False")。
public BindingList<工序合格率> 工序合格率显示 { get; set; } = new();
[AddINotifyPropertyChangedInterface]
public partial class 工序合格率
{
public int 序号 { get; set; }
public string 工位 { get; set; }
public string 测试总数 { get; set; }
public string 合格数 { get; set; }
public string 合格率 { get; set; }
}
List<工序合格率> 工序暂存 = new();
for (int i = 50; i < 410; i += 10)
{
var 合格temp = new Random().Next(10, 100);
var 总数 = new Random().Next(合格temp, 合格temp + 20);
var 合格率 = ((double)合格temp / 总数) * 100;
var temp = new 工序合格率()
{
工位 = $"OP{i}",
合格数 = 合格temp.ToString(),
测试总数 = 总数.ToString(),
合格率 = 合格率.ToString("0.0") + "%"//93.3%
};
工序暂存.Add(temp);
}
int ii = 1;
foreach (var item in 工序暂存.OrderByDescending(s => Convert.ToDouble(s.合格率.Replace("%", string.Empty))))
{
item.序号 = ii;
工序合格率显示.Add(item);
ii++;
}使用LiveChartsCore.SkiaSharpView创建图表
<lvc:PieChart x:Name="饼图_站点在线情况" LegendPosition="Right" Series="{Binding 在线情况Series}" LegendTextPaint="{Binding 白色}" Grid.ColumnSpan="2"/>折线图 (LineChart)用于显示数据的趋势,常用于时间序列分析。
柱状图 (ColumnChart)用于显示不同类别的数值对比,适合展示各类数据的差异。
条形图 (BarChart)和柱状图类似,区别在于条形图是水平显示的。
区域图 (AreaChart)区域图类似于折线图,但线下方的区域被填充,常用于显示累积数据或多层数据的堆叠。
雷达图 (RadarChart)雷达图通常用于显示多变量数据,图形呈现多边形状,适合比较多个维度的数值。等
LegendPosition="Right": 设置图例的位置为右侧。Series="{Binding 在线情况Series}": 数据绑定
LegendTextPaint="{Binding 白色}": 设置图例文本的颜色为白色
public SolidColorPaint 白色 { get; set; } = new SolidColorPaint(SKColors.White);//运行情况饼图数据绑定
public IEnumerable<ISeries> 运行状态Series { get; set; } =
[
new PieSeries<int>
{
Values= new []{3},
Fill = new SolidColorPaint(SKColor.Parse("#2196f3")),
Name = "待机中"//中文名称
},
new PieSeries<int>
{
Values= new []{1},
Fill = new SolidColorPaint(SKColors.Black),
Name = "加工中"//中文名称
},
new PieSeries<int>
{
Values= new []{2},
Fill = new SolidColorPaint(SKColors.Purple),
Name = "米诺"//中文名称
},
new PieSeries<int>
{
Values= new []{4},
Fill = new SolidColorPaint(SKColor.Parse("#f44336")),
Name = "故障中"//中文名称
},
new PieSeries<int>
{
Values= new []{3},
Fill = new SolidColorPaint(SKColors.Plum),
Name = "离线"//中文名称
},
];在app.xaml.cs中添加
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//var fontPath = Path.Combine(Directory.GetCurrentDirectory(), "字体", "MiSans.ttf");
//var typeface = SKTypeface.FromFile(fontPath);
//LiveCharts.Configure(config => config.HasGlobalSKTypeface(typeface));
var index = SKFontManager.Default.FontFamilies.ToList().IndexOf("黑体");
var songtiTypeface = SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);
LiveCharts.Configure(config => config.HasGlobalSKTypeface(songtiTypeface).AddDarkTheme().AddLightTheme());
}
如果同时安装了LiveCharts.Wpf
LiveChartsCore.LiveCharts.Configure支持中文显示
<lvc:CartesianChart> 是一个用于展示二维坐标图表的控件,它支持线图、柱状图、区域图等类型的图表。你可以通过设置 Series、XAxis 和 YAxis 来定义图表的外观和数据。
<lvc:CartesianChart DataContext="{Binding OEE}" LegendPosition="Hidden" LegendTextPaint="{Binding 白色}"
YAxes="{Binding YAxes}"
XAxes="{Binding XAxes}"
Series="{Binding 数据}">
</lvc:CartesianChart>Series:这个绑定指定了图表的系列数据,在这里是一个线图
XAxes 和 YAxes:这两个绑定分别设置了 X 轴和 Y 轴的显示内容,例如标签、格式等。
定义一个VM类,变量要用小驼峰命名法,变量与绑定的变量一致
[INotifyPropertyChanged]
public partial class 折线图ModelView
{
[ObservableProperty]
private LabelVisual _Title;
[ObservableProperty]
private IEnumerable<ISeries> _数据;
[ObservableProperty]
private Axis[] _XAxes;
[ObservableProperty]
private Axis[] _YAxes;
}public 折线图ModelView 工位合格率 { get; set; } = new();
public 折线图ModelView 线体直通率 { get; set; }
public 折线图ModelView OEE { get; set; }
private CancellationTokenSource 工位Token = new();
private CancellationTokenSource 线体Token = new();
private CancellationTokenSource OEEToken = new();
private Queue<DateTime> 线体时间队列 { get; set; } = new();
private Queue<DateTime> OEE时间队列 { get; set; } = new();
private void MetroWindow_Loaded(object sender, RoutedEventArgs e)
{
工站合格率初始化();
线体直通率初始化();
OEE初始化();
采集数据();
}
private void MetroWindow_Closed(object sender, EventArgs e)
{
工位Token.Cancel();
线体Token.Cancel();
OEEToken.Cancel();
}#region 采集数据
private void 采集数据()
{
Task.Run(async () =>
{
while (true)
{
lock (lockObj)
{
采集工位合格率数据();
// 调用自动翻页逻辑
}
await Task.Delay(5000);
自动翻页();
}
}, 工位Token.Token);
Task.Run(async () =>
{
while (true)
{
//await Task.Delay(TimeSpan.FromHours(1)); // 等待 1 小时
await Task.Delay(5000);
lock (lockObj)
{
采集线体直通率数据();
}
}
}, 线体Token.Token);
Task.Run(async () =>
{
while (true)
{
//await Task.Delay(TimeSpan.FromHours(1)); // 等待 1 小时
await Task.Delay(5000);
lock (lockObj)
{
采集OEE数据();
}
}
}, OEEToken.Token);
}
private void 采集线体直通率数据()
{
// 将当前时间加入队列
线体时间队列.Enqueue(DateTime.Now);
// 如果队列超过 8 个数据,删除第一个数据
if (线体时间队列.Count > 8)
{
线体时间队列.Dequeue();
}
// 切换到 UI 线程更新界面
Application.Current.Dispatcher.Invoke(() =>
{
// 更新图表的 X 轴标签ds
线体直通率.XAxes.First().Labels = 线体时间队列
.Select(t => t.ToString("HH:mm"))
.ToList();
线体直通率.数据.First().Values = 计算线体直通率(startTime, endTime);
});
}
private void 采集OEE数据()
{
OEE时间队列.Enqueue(DateTime.Now);
if (OEE时间队列.Count > 8)
{
OEE时间队列.Dequeue();
}
// 切换到 UI 线程更新界面
Application.Current.Dispatcher.Invoke(() =>
{
// 更新图表的 X 轴标签ds
OEE.XAxes.First().Labels = OEE时间队列
.Select(t => t.ToString("HH:mm"))
.ToList();
OEE.数据.First().Values = 计算OEE(startTime, endTime);
});
}
private void 采集工位合格率数据()
{
运行工站 = JsonSerializer.Deserialize<List<string>>(File.ReadAllText(Path.Combine(系统参数.配置文件路径, "运行工站.json")));
Application.Current.Dispatcher.Invoke(() =>
{
工位合格率.数据.First().Values = 计算各站合格率(startTime, endTime);
工位合格率.XAxes.First().Labels = 运行工站;
});
}
#endregion#region 初始化
private void 线体直通率初始化()
{
线体时间队列 = new Queue<DateTime>();
线体时间队列.Enqueue(DateTime.Now);
var 时间标签 = 线体时间队列.Select(t => t.ToString("HH:mm")).ToList();
List<ISeries<double>> re =
[
new LineSeries<double>()
{
Name = "直通率",
Fill = null,
Values = new List<double>(),
GeometrySize = 8,
Stroke = new SolidColorPaint(SKColors.Cyan) { StrokeThickness = 6 },
DataLabelsPosition =LiveChartsCore.Measure.DataLabelsPosition.Start,
DataLabelsSize=12,
DataLabelsFormatter = point => $"{point.Coordinate.PrimaryValue:0}%", // 设置标签格式
DataLabelsPaint = new SolidColorPaint(SKColors.White), // 标签颜色
}
];
线体直通率 = new()
{
数据 = re,
XAxes =
[
new Axis()
{
LabelsPaint = new SolidColorPaint(SKColors.White){IsAntialias = true},
TextSize=14,
ShowSeparatorLines = false,
ForceStepToMin=true,
Labels = 时间标签,
LabelsRotation=0,
TicksPaint = new SolidColorPaint(SKColors.White) { IsAntialias = true }, // 设置刻度线的颜色
DrawTicksPath=true,
}
],
YAxes =
[
new Axis()
{
LabelsPaint = new SolidColorPaint(SKColors.White) { IsAntialias = true },
MaxLimit = 110,
MinLimit = 0,
TextSize = 14,
MinStep = 20,
Labeler = value=>$"{value:0}%", // 防止空标签导致问题
ShowSeparatorLines = false,
ForceStepToMin=true
}
],
};
re[0].Values = 计算线体直通率(startTime, endTime);
}
private void 工站合格率初始化()
{
List<ISeries<double>> re =
[
new LineSeries<double>()
{
Name = "合格率",
Fill = null,
//Values = new List<double>(),
GeometrySize = 8,
Stroke = new SolidColorPaint(SKColors.Cyan) { StrokeThickness = 6 },
DataLabelsPosition =LiveChartsCore.Measure.DataLabelsPosition.Start,
DataLabelsSize=12,
DataLabelsFormatter = point => $"{point.Coordinate.PrimaryValue:F2}%", // 设置标签格式
DataLabelsPaint = new SolidColorPaint(SKColors.White), // 标签颜色
}
];
工位合格率 = new()
{
//new LineSeries<> 生成随机数据(DateTime.Now, 4)
数据 = re,
XAxes =
[
new Axis()
{
LabelsPaint = new SolidColorPaint(SKColors.White){IsAntialias = true},
TextSize=14,
ShowSeparatorLines = false,
ForceStepToMin=true,
Labels = 运行工站,
LabelsRotation=-30,
TicksPaint = new SolidColorPaint(SKColors.White) { IsAntialias = true }, // 设置刻度线的颜色
DrawTicksPath=true,// 启用坐标轴绘制
MinLimit=-0.5,
MaxLimit=3.5
}
],
YAxes =
[
new Axis()
{
LabelsPaint = new SolidColorPaint(SKColors.White) { IsAntialias = true },
MaxLimit = 110,
MinLimit = 0,
TextSize = 14,
MinStep = 20,
Labeler = value=>$"{value:0}%", // 防止空标签导致问题
ShowSeparatorLines = false,
ForceStepToMin=true
}
],
};
re[0].Values = 计算各站合格率(startTime, endTime);
}
private void OEE初始化()
{
OEE时间队列 = new Queue<DateTime>();
OEE时间队列.Enqueue(DateTime.Now);
var 时间标签 = OEE时间队列.Select(t => t.ToString("HH:mm")).ToList();
List<ISeries<double>> re =
[
new LineSeries<double>()
{
Name = "OEE",
Fill = null,
Values = new List<double>(),
GeometrySize = 8,
Stroke = new SolidColorPaint(SKColors.Cyan) { StrokeThickness = 6 },
DataLabelsPosition =LiveChartsCore.Measure.DataLabelsPosition.Start,
DataLabelsSize=12,
DataLabelsFormatter = point => $"{point.Coordinate.PrimaryValue:0.0}%", // 设置标签格式
DataLabelsPaint = new SolidColorPaint(SKColors.White), // 标签颜色
}
];
OEE = new()
{
数据 = re,
XAxes =
[
new Axis()
{
LabelsPaint = new SolidColorPaint(SKColors.White){IsAntialias = true},
TextSize=14,
ShowSeparatorLines = false,
ForceStepToMin=true,
Labels = 时间标签,
LabelsRotation=0,
TicksPaint = new SolidColorPaint(SKColors.White) { IsAntialias = true }, // 设置刻度线的颜色
DrawTicksPath=true,
MinLimit=-0.5,
}
],
YAxes =
[
new Axis()
{
LabelsPaint = new SolidColorPaint(SKColors.White) { IsAntialias = true },
MaxLimit = 120,
MinLimit = 0,
TextSize = 14,
MinStep = 40,
Labeler = value=>$"{value:0}%", // 防止空标签导致问题
ShowSeparatorLines = false,
ForceStepToMin=true
}
],
};
re[0].Values = 计算OEE(startTime, endTime);
}
#endregion#region 计算数据
private void 自动翻页()
{
// 获取总页数
int totalPages = (int)Math.Ceiling((double)运行工站.Count / pageSize);
// 根据方向更新当前页
if (isForward)
{
currentPage++;
// 如果超过最后一页,切换方向并停留在最后一页
if (currentPage >= totalPages)
{
currentPage = totalPages - 1;
isForward = false; // 切换为向后翻页
}
}
else
{
currentPage--;
// 如果低于第一页,切换方向并停留在第一页
if (currentPage < 0)
{
currentPage = 0;
isForward = true; // 切换为向前翻页
}
}
// 更新分页后的 X 轴范围
工位合格率.XAxes.First().MinLimit = currentPage * pageSize - 0.5; // 给点留空
工位合格率.XAxes.First().MaxLimit = Math.Min((currentPage + 1) * pageSize, 运行工站.Count) - 0.5;
}
private List<double>? 计算线体直通率(string startTime, string endTime)
{
try
{
var 生产实时信息 = 数据库.生产实时信息.AsNoTracking().Where(s => string.Compare(s.updateTime, startTime) >= 0 && string.Compare(s.updateTime, endTime) <= 0).ToList();
if (生产实时信息 == null)
{
return null;
}
var 总数 = 生产实时信息.Count;
var 合格数 = 生产实时信息.Count(s => s.isbad == false);
if (总数 == 0)
{
线体直通数据.Add(100);
}
else
{
线体直通数据.Add((double)合格数 / 总数 * 100);
}
if (线体直通数据.Count > 8)
{
线体直通数据.RemoveAt(0);
}
return 线体直通数据;
}
catch (Exception ex)
{
throw ex;
}
}
private List<double>? 计算各站合格率(string startTime, string endTime)
{
try
{
工站运行总数.Clear();
工站运行错误数.Clear();
//避免缓存查询结果
var 生产实时信息 = 数据库.生产实时信息.AsNoTracking().Where(s => string.Compare(s.updateTime, startTime) >= 0 && string.Compare(s.updateTime, endTime) <= 0).ToList();
if (生产实时信息 == null)
{
return null;
}
var re = new List<double>();
for (int i = 0; i < 运行工站.Count; i++)
{
工站运行总数.Add(0);
工站运行错误数.Add(0);
}
foreach (var info in 生产实时信息)
{
if (info.stationCode == "0")
{
continue;
}
if ((bool)info.isbad)
{
var index = 运行工站.IndexOf(info.ngStation);
for (int i = 0; i <= index; i++)
{
工站运行总数[i]++;
}
工站运行错误数[index]++;
}
else if (string.IsNullOrWhiteSpace(info.stationCode))
{
for (int i = 0; i < 运行工站.Count; i++)
{
工站运行总数[i]++;
}
}
else
{
var index = 运行工站.IndexOf(info.stationCode);
for (int i = 0; i <= index; i++)
{
工站运行总数[i]++;
}
}
}
for (int j = 0; j < 工站运行总数.Count; j++)
{
if (工站运行总数[j] == 0)
{
re.Add(100);
}
else
{
re.Add((1 - (double)工站运行错误数[j] / 工站运行总数[j]) * 100);
}
}
return re;
}
catch (Exception ex)
{
throw ex;
}
}
private List<double>? 计算OEE(string startTime, string endTime)
{
var 设备信息 = 数据库.设备实时信息.AsNoTracking().ToList();
var 生产实时信息 = 数据库.生产实时信息.AsNoTracking().Where(s => string.Compare(s.updateTime, startTime) >= 0 && string.Compare(s.updateTime, endTime) <= 0).ToList();
var 生产节拍信息 = 数据库.生产节拍信息.AsNoTracking().ToList();
int 设备运转时间 = 0;
int 负荷时间 = 0;
int 实际生产数量 = 0;
int 合格品数量 = 0;
int 生产数量 = 0;
foreach (var item in 设备信息)
{
设备运转时间 += Convert.ToInt32(item.totalRunningDuration);
负荷时间 += Convert.ToInt32(item.totalOnLineDuration);
}
负荷时间 = 设备运转时间 - 负荷时间;
double 时间稼动率 = (double)设备运转时间 / 负荷时间;
foreach (var item in 生产实时信息)
{
if (item.isbad == true || string.IsNullOrWhiteSpace(item.stationCode))
{
var 对应产品理论生产节拍 = 生产节拍信息.Where(x => x.StationCode == item.snNumber).Select(x => x.TheoreticalTempo).FirstOrDefault();
实际生产数量 += 对应产品理论生产节拍;
生产数量++;
}
if (item.isbad == false && string.IsNullOrWhiteSpace(item.stationCode))
{
合格品数量++;
}
}
double 性能稼动率 = (double)实际生产数量 / 设备运转时间;
double 产品合格率 = (double)合格品数量 / 生产数量;
设备OEE数据.Add(性能稼动率 * 产品合格率 * 时间稼动率 * 100);
if (设备OEE数据.Count > 8)
{
设备OEE数据.RemoveAt(0);
}
return 设备OEE数据;
}
#endregion画刷
1.LinearGradientBrush,这种画刷是由左上角向右下.
2.RadialGradientBrush,这种画刷是有中心向外面渐变(此项目使用这种)
<!--设计背景颜色渐变-->
<Grid.Background>
<RadialGradientBrush>
<GradientStop Color="#ff285173" Offset="0"></GradientStop>
<GradientStop Color="#ff244967" Offset="0.5"></GradientStop>
<GradientStop Color="#13164B" Offset="1"></GradientStop>
</RadialGradientBrush>
