using RealTimeGraphX.EventArguments; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; 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 RealTimeGraphX.WPF { /// /// Represents a horizontal/vertical graph axis component. /// /// public class WpfGraphAxisControl : WpfGraphComponentBase { private ItemsControl _items_control; private WpfGraphAxisPanel _axisPanel; /// /// Initializes the class. /// static WpfGraphAxisControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(WpfGraphAxisControl), new FrameworkPropertyMetadata(typeof(WpfGraphAxisControl))); } /// /// Gets or sets the control orientation. /// public Orientation Orientation { get { return (Orientation)GetValue(OrientationProperty); } set { SetValue(OrientationProperty, value); } } public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(WpfGraphAxisControl), new PropertyMetadata(Orientation.Vertical)); public double AxisLabelAngle { get { return (double)GetValue(AxisLabelAngleProperty); } set { SetValue(AxisLabelAngleProperty, value); } } // Using a DependencyProperty as the backing store for AxisLabelAngle. This enables animation, styling, binding, etc... public static readonly DependencyProperty AxisLabelAngleProperty = DependencyProperty.Register("AxisLabelAngle", typeof(double), typeof(WpfGraphAxisControl), new PropertyMetadata(-30.0)); /// /// Gets or sets the tick item template. /// public DataTemplate ItemTemplate { get { return (DataTemplate)GetValue(ItemTemplateProperty); } set { SetValue(ItemTemplateProperty, value); } } public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(WpfGraphAxisControl), new PropertyMetadata(null)); /// /// Gets or sets the tick items. /// internal ObservableCollection Items { get { return (ObservableCollection)GetValue(ItemsProperty); } set { SetValue(ItemsProperty, value); } } public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection), typeof(WpfGraphAxisControl), new PropertyMetadata(null)); /// /// Gets or sets the number of ticks to display on the control. /// public int Ticks { get { return (int)GetValue(TicksProperty); } set { SetValue(TicksProperty, value); } } public static readonly DependencyProperty TicksProperty = DependencyProperty.Register("Ticks", typeof(int), typeof(WpfGraphAxisControl), new PropertyMetadata(9, (d, e) => (d as WpfGraphAxisControl).OnTicksChanged())); /// /// Gets or sets the string format which is used to format the ticks value. /// public String StringFormat { get { return (String)GetValue(StringFormatProperty); } set { SetValue(StringFormatProperty, value); } } public static readonly DependencyProperty StringFormatProperty = DependencyProperty.Register("StringFormat", typeof(String), typeof(WpfGraphAxisControl), new PropertyMetadata(null)); /// /// When overridden in a derived class, is invoked whenever application code or internal processes call . /// public override void OnApplyTemplate() { base.OnApplyTemplate(); _items_control = GetTemplateChild("PART_ItemsControl") as ItemsControl; _items_control.Loaded += (x, e) => { ItemsPresenter itemsPresenter = GetVisualChild(_items_control); _axisPanel = VisualTreeHelper.GetChild(itemsPresenter, 0) as WpfGraphAxisPanel; }; OnTicksChanged(); } private static T GetVisualChild(DependencyObject parent) where T : Visual { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); child = v as T; if (child == null) { child = GetVisualChild(v); } if (child != null) { break; } } return child; } /// /// Called when the property has changed. /// protected virtual void OnTicksChanged() { Items = new ObservableCollection(Enumerable.Range(0, Ticks).Select(x => new WpfGraphAxisTickData())); Controller?.RequestVirtualRangeChange(); _axisPanel?.UpdatePanel(); } protected override void OnControllerChanged(IGraphController oldController, IGraphController newController) { base.OnControllerChanged(oldController, newController); if (newController != null) { newController.RequestVirtualRangeChange(); } } /// /// Handles the event. /// /// The source of the event. /// The event arguments. protected override void OnVirtualRangeChanged(object sender, RangeChangedEventArgs e) { InvokeUI(() => { if (Orientation == Orientation.Vertical) { if (Items != null) { var steps = e.MinimumY.CreateRange(e.MinimumY, e.MaximumY, Ticks).Reverse().ToList(); for (int i = 0; i < steps.Count; i++) { var tick_data = Items[i]; tick_data.Data = steps[i]; tick_data.DisplayText = tick_data.Data.ToString(StringFormat); tick_data.IsFirst = i == 0; tick_data.IsLast = i == steps.Count - 1; tick_data.IsEven = i % 2 == 0; } } } else { if (Items != null) { var steps = e.MinimumX.CreateRange(e.MinimumX, e.MaximumX, Ticks).ToList(); for (int i = 0; i < steps.Count; i++) { var tick_data = Items[i]; tick_data.Data = steps[i]; tick_data.DisplayText = tick_data.Data.ToString(StringFormat); tick_data.IsFirst = i == 0; tick_data.IsLast = i == steps.Count - 1; tick_data.IsEven = i % 2 == 0; } } } }); } } }