using GraphicData.Class; using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace GraphicData.User_Control { public partial class uDataGraph : UserControl { public uDataGraph() { InitializeComponent(); } #region Variables int DataDurationStart = 0; int DataDurationEnd = 0; int DataDurationTotal = 0; bool ReducedTimeStamps = false; DateTime firstTime; #endregion #region Properties public List JsonData { get { return (List)GetValue(JsonDataProperty); } set { SetValue(JsonDataProperty, value); } } // Using a DependencyProperty as the backing store for JsonData. This enables animation, styling, binding, etc... public static readonly DependencyProperty JsonDataProperty = DependencyProperty.Register("JsonData", typeof(List), typeof(uDataGraph), new PropertyMetadata(new List(), new PropertyChangedCallback(HandleDependancyPropertyChanged))); public int IndexTime { get { return (int)GetValue(IndexTimeProperty); } set { SetValue(IndexTimeProperty, value); } } // Using a DependencyProperty as the backing store for IndexTime. This enables animation, styling, binding, etc... public static readonly DependencyProperty IndexTimeProperty = DependencyProperty.Register("IndexTime", typeof(int), typeof(uDataGraph), new PropertyMetadata(0, new PropertyChangedCallback(HandleDependancyPropertyChanged))); public int IndexValue { get { return (int)GetValue(IndexValueProperty); } set { SetValue(IndexValueProperty, value); } } // Using a DependencyProperty as the backing store for IndexValue. This enables animation, styling, binding, etc... public static readonly DependencyProperty IndexValueProperty = DependencyProperty.Register("IndexValue", typeof(int), typeof(uDataGraph), new PropertyMetadata(1, new PropertyChangedCallback(HandleDependancyPropertyChanged))); public int IndexDuration { get { return (int)GetValue(IndexDurationProperty); } set { SetValue(IndexDurationProperty, value); } } // Using a DependencyProperty as the backing store for IndexDuration. This enables animation, styling, binding, etc... public static readonly DependencyProperty IndexDurationProperty = DependencyProperty.Register("IndexDuration", typeof(int), typeof(uDataGraph), new PropertyMetadata(2, new PropertyChangedCallback(HandleDependancyPropertyChanged))); public int WarningThreshold { get { return (int)GetValue(WarningThresholdProperty); } set { SetValue(WarningThresholdProperty, value); } } // Using a DependencyProperty as the backing store for WarningThreshold. This enables animation, styling, binding, etc... public static readonly DependencyProperty WarningThresholdProperty = DependencyProperty.Register("WarningThreshold", typeof(int), typeof(uDataGraph), new PropertyMetadata(40, new PropertyChangedCallback(HandleDependancyPropertyChanged))); public int ErrorThreshold { get { return (int)GetValue(ErrorThresholdProperty); } set { SetValue(ErrorThresholdProperty, value); } } // Using a DependencyProperty as the backing store for ErrorThreshold. This enables animation, styling, binding, etc... public static readonly DependencyProperty ErrorThresholdProperty = DependencyProperty.Register("ErrorThreshold", typeof(int), typeof(uDataGraph), new PropertyMetadata(60, new PropertyChangedCallback(HandleDependancyPropertyChanged))); public bool IsThresholdActive { get { return (bool)GetValue(IsThresholdActiveProperty); } set { SetValue(IsThresholdActiveProperty, value); } } // Using a DependencyProperty as the backing store for IsThresholdActive. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsThresholdActiveProperty = DependencyProperty.Register("IsThresholdActive", typeof(bool), typeof(uDataGraph), new PropertyMetadata(false, new PropertyChangedCallback(HandleDependancyPropertyChanged))); public string GraphicTitle { get { return (string)GetValue(GraphicTitleProperty); } set { SetValue(GraphicTitleProperty, value); } } // Using a DependencyProperty as the backing store for GraphicTitle. This enables animation, styling, binding, etc... public static readonly DependencyProperty GraphicTitleProperty = DependencyProperty.Register("GraphicTitle", typeof(string), typeof(uDataGraph), new PropertyMetadata("CPU-Auslastung", new PropertyChangedCallback(HandleDependancyPropertyChanged))); private static void HandleDependancyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if(!(d is uDataGraph me)) return; me.BindingValueChange(); } #endregion #region Binding public void BindingValueChange() { if (JsonData == null || JsonData.Count <= 0) return; GraphicCanvas.Children.Clear(); TimeStampGrid.Children.Clear(); TimeStampGrid.ColumnDefinitions.Clear(); GraphicDataProperty.Clear(); ReducedTimeStamps = false; FillGraphicDataProperty(); FillVariables(); CreateDateTitle(); SetCanvasBorderPadding(); CreateTimeStamps(); DrawGraphicData(); } #endregion #region GraphicDataProperty public List GraphicDataProperty { get; set; } = new List(); public void FillGraphicDataProperty() { var reverseData = JsonData.ToList(); reverseData.Reverse(); if ((DateTime)reverseData[0][IndexTime] < (DateTime)reverseData[reverseData.Count() - 1][IndexTime]) { foreach (var item in reverseData) { cGraphicData data = new cGraphicData(); data.DataValue = (double)item[IndexValue]; data.DataDuration = int.Parse(item[IndexDuration].ToString()); data.DataTime = (DateTime)item[IndexTime]; data.DataTime = data.DataTime.AddHours(2); GraphicDataProperty.Add(data); } } else if ((DateTime)JsonData[0][IndexTime] < (DateTime)JsonData[JsonData.Count() - 1][IndexTime]) { foreach (var item in JsonData) { cGraphicData data = new cGraphicData(); data.DataValue = (double)item[IndexValue]; data.DataDuration = int.Parse(item[IndexDuration].ToString()); data.DataTime = (DateTime)item[IndexTime]; data.DataTime = data.DataTime.AddHours(2); GraphicDataProperty.Add(data); } } } #endregion #region FillVariables public void FillVariables() { firstTime = GraphicDataProperty.First().DataTime; DateTime lastTime = GraphicDataProperty.Last().DataTime; int lastDuration = GraphicDataProperty.Last().DataDuration; lastTime = lastTime.AddMilliseconds(lastDuration); DataDurationStart = firstTime.Hour; if(lastTime.Minute != 0) { lastTime = lastTime.AddMinutes(60 - (lastDuration/60000)); } DataDurationEnd = lastTime.Hour; DataDurationTotal = DataDurationEnd - DataDurationStart; if (firstTime.Day < lastTime.Day) { if (DataDurationTotal < 2) { DataDurationTotal = (24 - DataDurationStart) + DataDurationEnd; } } if(DataDurationTotal > 10) { ReducedTimeStamps = true; if(DataDurationTotal % 2 == 1) { DataDurationTotal += 1; } } } #endregion #region Create Date Title public void CreateDateTitle() { DateTime dataDate = GraphicDataProperty.First().DataTime; dataDate = dataDate.Date; DateBlock.Text = dataDate.ToString("dddd, dd.MM.yyyy"); TitleBlock.Text = GraphicTitle; } #endregion #region SetCanvasBorderPadding public void SetCanvasBorderPadding() { double borderWidth = GraphicBorder.ActualWidth; double paddingWidth = borderWidth / (((double)DataDurationTotal + 1)* 2.0); double borderHeight = GraphicBorder.ActualHeight; double paddingHeight = borderHeight / 10.0; GraphicBorder.Padding = new Thickness(0); GraphicBorder.Padding = new Thickness(paddingWidth, paddingHeight - 4, paddingWidth, paddingHeight - 4); GraphicBorder.UpdateLayout(); CanvasBorder.UpdateLayout(); } #endregion #region Time Stamps public void CreateTimeStamps() { SolidColorBrush customBrush = (SolidColorBrush)Application.Current.Resources["color9B9B9B"]; for (int i = 0; i <= DataDurationTotal; i++) { ColumnDefinition timeStamp = new ColumnDefinition(); timeStamp.Width = new GridLength(1, GridUnitType.Star); TimeStampGrid.ColumnDefinitions.Add(timeStamp); if (ReducedTimeStamps == true && i % 2 == 1) { continue; } TextBlock TimeStampText = new TextBlock() { Text = (firstTime.AddHours(i)).Hour.ToString() + ":00", FontFamily = new FontFamily("Calibri"), FontSize = 11, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, Foreground = customBrush, TextAlignment = TextAlignment.Center, TextTrimming = TextTrimming.None, }; if(DataDurationTotal > 20) { TimeStampText.Margin = new Thickness(-2,0,-2,0); } Grid.SetColumn(TimeStampText, i); TimeStampGrid.Children.Add(TimeStampText); } } #endregion #region Draw Data public double CalculateSetLeft(DateTime dataTime) { double setLeft = (double)dataTime.Hour + ((double)dataTime.Minute / 60.0); setLeft = (setLeft - (double)DataDurationStart) * ((double)CanvasBorder.ActualWidth / ((double)DataDurationTotal)); return setLeft; } public void DrawGraphicData() { double setLeft = 0.0; double setFactor = 0.0; setFactor = (GraphicCanvas.ActualHeight - 8.0) / 100.0; foreach (var data in GraphicDataProperty) { DateTime dataTime = data.DataTime; double dataValue = data.DataValue; int dataDuration = data.DataDuration; Border border = new Border { Height = 8.0, Width = (double)dataDuration * ((double)CanvasBorder.ActualWidth / ((double)DataDurationTotal)) / 3600000.0, CornerRadius = new CornerRadius(4.0), ToolTip = dataTime.ToShortTimeString() + " - " + dataTime.AddMilliseconds(dataDuration).ToShortTimeString() + " | " + (int)dataValue + "%" }; if(border.Width < 8) { border.Width = 8; } if(IsThresholdActive == false) { border.Background = new SolidColorBrush(Color.FromRgb(0, 157, 221)); } else if(dataValue >= ErrorThreshold) { border.Background = new SolidColorBrush(Color.FromRgb(206, 61, 54)); } else if(dataValue >= WarningThreshold) { border.Background = new SolidColorBrush(Color.FromRgb(251, 157, 40)); } else { border.Background = new SolidColorBrush(Color.FromRgb(117, 177, 89)); } setLeft = CalculateSetLeft(dataTime); Canvas.SetBottom(border, dataValue * setFactor); Canvas.SetLeft(border, setLeft); GraphicCanvas.Children.Add(border); } } #endregion #region Close Button private void Border_MouseEnter(object sender, MouseEventArgs e) { SolidColorBrush customBrush = (SolidColorBrush)Application.Current.Resources["color009DDD"]; CloseButton.PrimaryIconColor = customBrush; } private void Border_MouseLeave(object sender, MouseEventArgs e) { SolidColorBrush customBrush = (SolidColorBrush)Application.Current.Resources["color9B9B9B"]; CloseButton.PrimaryIconColor = customBrush; } private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Close_Window(); } private void Border_TouchDown(object sender, TouchEventArgs e) { Close_Window(); } private Window GetMainWindow() { DependencyObject parent = VisualTreeHelper.GetParent(this); while (parent != null && !(parent is Window)) { parent = VisualTreeHelper.GetParent(parent); } return parent as Window; } private void Close_Window() { Window mainWindow = Window.GetWindow(this); if (mainWindow != null) { mainWindow.Close(); } } #endregion } }