From 9d4f81bc1f6bc39de09ed464676a37b2ce6874cc Mon Sep 17 00:00:00 2001 From: YokeshSF4393 Date: Thu, 4 Jun 2026 14:58:51 +0530 Subject: [PATCH] 1027279: Fixed issues and moved from changes in charts. --- .../Charts/AxisConfiguration/AxisLabels.razor | 12 ++ .../BubbleAndScatterCharts/BubbleChart.razor | 5 - .../Charts/LineCharts/SteplineChart.razor | 5 +- .../AxisTypeRenderer/DateTimeAxisRenderer.cs | 24 ++-- .../Charts/Chart/Series/ChartSeries.cs | 4 +- .../Charts/Chart/SfChart.razor.JsInterop.cs | 2 +- .../Charts/Chart/SfChart.razor.LifeCycle.cs | 126 +++++++++--------- .../Charts/Chart/SfChart.razor.Members.cs | 58 +++++--- .../Charts/Chart/SfChart.razor.Methods.cs | 18 +-- .../Chart/SfChart.razor.PointerEvents.cs | 4 +- src/Components/Charts/Chart/SfChart.razor.cs | 101 ++++++++------ src/wwwroot/scripts/chart.js | 12 +- 12 files changed, 211 insertions(+), 160 deletions(-) diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor index a2b9d4d..1a9480d 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor @@ -238,6 +238,7 @@ LabelFormat="{value}B" LabelPosition="@CurrentLabelPosition" LabelIntersectAction="LabelIntersectAction.Rotate90"> + @@ -679,6 +680,11 @@ CurrentLabelPosition = position; } } + + private string LabelColor => + CurrentLabelPosition == Syncfusion.Blazor.Toolkit.AxisPosition.Inside + ? "black" + : null; // EDGE LABEL STATE private EdgeLabelPlacement CurrentEdgePlacement { get; set; } @@ -964,6 +970,7 @@ LabelFormat=""{value}B"" LabelPosition=""@CurrentLabelPosition"" LabelIntersectAction=""LabelIntersectAction.Rotate90""> + @@ -1006,6 +1013,11 @@ CurrentLabelPosition = position; } } + + private string LabelColor => + CurrentLabelPosition == Syncfusion.Blazor.Toolkit.AxisPosition.Inside + ? ""black"" + : null; private List PopulationData = new() { diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/BubbleChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/BubbleChart.razor index e9c5606..d91dc23 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/BubbleChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/BubbleChart.razor @@ -764,9 +764,4 @@ _currentTheme = CurrentTheme; } -} -{ -_currentTheme = CurrentTheme; -} - } \ No newline at end of file diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor index 8a8cbba..a31cf11 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor @@ -128,7 +128,9 @@ Fill="#0FAF9C" Type="ChartSeriesType.StepLine"> - + + + @@ -571,6 +573,7 @@ private string AustraliaColor => IsDarkTheme ? "#EE884E" : "#E3651D"; private string CustomizedSeriesColor => IsDarkTheme ? "#F44F80" : "#D71D55"; + private string TextColor => IsDarkTheme ? "#E6EEF8" : "#0B1F3B"; // Current step position private StepPosition CurrentStepPosition { get; set; } = StepPosition.Left; diff --git a/src/Components/Charts/Chart/Renderer/AxisRenderer/AxisTypeRenderer/DateTimeAxisRenderer.cs b/src/Components/Charts/Chart/Renderer/AxisRenderer/AxisTypeRenderer/DateTimeAxisRenderer.cs index f9db37c..d482a32 100644 --- a/src/Components/Charts/Chart/Renderer/AxisRenderer/AxisTypeRenderer/DateTimeAxisRenderer.cs +++ b/src/Components/Charts/Chart/Renderer/AxisRenderer/AxisTypeRenderer/DateTimeAxisRenderer.cs @@ -137,12 +137,14 @@ private void GetHour(DateTime minimum, DateTime maximum, ChartRangePadding range if (rangePadding == ChartRangePadding.Round) { Min = GetTime(new DateTime(minimum.Year, minimum.Month, minimum.Day, hour, 0, 0)); - Max = GetTime(new DateTime(maximum.Year, maximum.Month, maximum.Day, endHour, 59, 59)); + Max = GetTime(new DateTime(maximum.Year, maximum.Month, maximum.Day, Math.Min(endHour, 23), 59, 59)); } else { - Min = GetTime(new DateTime(minimum.Year, minimum.Month, minimum.Day, hour + (int)-interval, 0, 0)); - Max = GetTime(new DateTime(maximum.Year, maximum.Month, maximum.Day, endHour + (int)interval, 0, 0)); + DateTime minDateTime = new DateTime(minimum.Year, minimum.Month, minimum.Day, hour, 0, 0).AddHours((int)-interval); + DateTime maxDateTime = new DateTime(maximum.Year, maximum.Month, maximum.Day, endHour, 0, 0).AddHours((int)interval); + Min = GetTime(minDateTime); + Max = GetTime(maxDateTime); } } @@ -194,12 +196,14 @@ private void ApplyMinutePadding(DateTime minimum, DateTime maximum, ChartRangePa if (rangePadding == ChartRangePadding.Round) { Min = GetTime(new DateTime(minimum.Year, minimum.Month, minimum.Day, minimum.Hour, minute, 0)); - Max = GetTime(new DateTime(maximum.Year, maximum.Month, minimum.Day, maximum.Hour, endMinute, 59)); + Max = GetTime(new DateTime(maximum.Year, maximum.Month, minimum.Day, maximum.Hour, Math.Min(endMinute, 59), 59)); } else { - Min = GetTime(new DateTime(minimum.Year, maximum.Month, minimum.Day, minimum.Hour, minute + (int)-interval, 0)); - Max = GetTime(new DateTime(maximum.Year, maximum.Month, maximum.Day, maximum.Hour, endMinute + (int)interval, 0)); + DateTime minDateTime = new DateTime(minimum.Year, minimum.Month, minimum.Day, minimum.Hour, minute, 0).AddMinutes((int)-interval); + DateTime maxDateTime = new DateTime(maximum.Year, maximum.Month, maximum.Day, maximum.Hour, endMinute, 0).AddMinutes((int)interval); + Min = GetTime(minDateTime); + Max = GetTime(maxDateTime); } } @@ -214,12 +218,14 @@ private void ApplySecondPadding(DateTime minimum, DateTime maximum, ChartRangePa if (rangePadding == ChartRangePadding.Round) { Min = GetTime(new DateTime(minimum.Year, minimum.Month, minimum.Day, minimum.Hour, minimum.Minute, second, 0)); - Max = GetTime(new DateTime(maximum.Year, maximum.Month, maximum.Day, maximum.Hour, maximum.Minute, endSecond, 0)); + Max = GetTime(new DateTime(maximum.Year, maximum.Month, maximum.Day, maximum.Hour, maximum.Minute, Math.Min(endSecond, 59), 0)); } else { - Min = GetTime(new DateTime(minimum.Year, minimum.Month, minimum.Day, minimum.Hour, minimum.Minute, second + (int)-interval, 0)); - Max = GetTime(new DateTime(maximum.Year, maximum.Month, maximum.Day, maximum.Hour, maximum.Minute, endSecond + (int)interval, 0)); + DateTime minDateTime = new DateTime(minimum.Year, minimum.Month, minimum.Day, minimum.Hour, minimum.Minute, second, 0).AddSeconds((int)-interval); + DateTime maxDateTime = new DateTime(maximum.Year, maximum.Month, maximum.Day, maximum.Hour, maximum.Minute, endSecond, 0).AddSeconds((int)interval); + Min = GetTime(minDateTime); + Max = GetTime(maxDateTime); } } diff --git a/src/Components/Charts/Chart/Series/ChartSeries.cs b/src/Components/Charts/Chart/Series/ChartSeries.cs index 702524d..d2ac388 100644 --- a/src/Components/Charts/Chart/Series/ChartSeries.cs +++ b/src/Components/Charts/Chart/Series/ChartSeries.cs @@ -1411,11 +1411,11 @@ public double ColumnWidthInPixel get => _columnWidthInPixel; set { - if (Math.Abs(_columnWidthInPixel - value) > double.Epsilon) + if (_columnWidthInPixel != value) { _columnWidthInPixel = value; - if (Renderer is not null && Renderer.Series is not null && Renderer.Series.Visible) + if (Renderer != null && Renderer.Series != null && Renderer.Series.Visible) { Renderer?.UpdateDirection(); } diff --git a/src/Components/Charts/Chart/SfChart.razor.JsInterop.cs b/src/Components/Charts/Chart/SfChart.razor.JsInterop.cs index b112551..f514d68 100644 --- a/src/Components/Charts/Chart/SfChart.razor.JsInterop.cs +++ b/src/Components/Charts/Chart/SfChart.razor.JsInterop.cs @@ -364,7 +364,7 @@ private async Task ResizeChartAsync(Size availabelSize) _isResizeTemplate = true; _ = UpdateLegendTemplateAsync(); } - if (_isSizeSet && _selectionModule is not null) + if (_render.IsSizeSet && _selectionModule is not null) { _ = _selectionModule.RemoveSelectedElementsAsync(); _selectionModule.InvokeSelection(); diff --git a/src/Components/Charts/Chart/SfChart.razor.LifeCycle.cs b/src/Components/Charts/Chart/SfChart.razor.LifeCycle.cs index a33c353..aa43653 100644 --- a/src/Components/Charts/Chart/SfChart.razor.LifeCycle.cs +++ b/src/Components/Charts/Chart/SfChart.razor.LifeCycle.cs @@ -38,24 +38,24 @@ protected override void OnInitialized() /// [EditorBrowsable(EditorBrowsableState.Never)] [Browsable(false)] - protected override void OnParametersSet() + protected override async Task OnParametersSetAsync() { - base.OnParametersSet(); + await base.OnParametersSetAsync(); ChartThemeStyle themeStyle = ChartHelper.GetChartThemeStyle(Theme.ToString()); if (_chartThemeStyle != themeStyle) { _chartThemeStyle = themeStyle; } - if (_updateLayout) + if (_layout.UpdateLayout) { - _updateLayout = false; - _ = OnDimensionChangedAsync(); + _layout.UpdateLayout = false; + await OnDimensionChangedAsync(); } - if (_isMultiSelect != AllowMultiSelection) + if (_selection.IsMultiSelect != AllowMultiSelection) { - _isMultiSelect = AllowMultiSelection; - _ = CallJSInteropForSelectionHighlightOptionAsync(_selectionModule is not null && _isScriptLoaded); + _selection.IsMultiSelect = AllowMultiSelection; + await CallJSInteropForSelectionHighlightOptionAsync(_selectionModule is not null && _isScriptLoaded); if (_selectionModule is not null) { _selectionModule.ClearDraggedRects(); @@ -64,10 +64,10 @@ protected override void OnParametersSet() } } - if (_highlightPattern != HighlightPattern) + if (_selection.HighlightPattern != HighlightPattern) { - _highlightPattern = HighlightPattern; - _ = CallJSInteropForSelectionHighlightOptionAsync(); + _selection.HighlightPattern = HighlightPattern; + await CallJSInteropForSelectionHighlightOptionAsync(); if (_highlightModule is not null) { _highlightModule.CallSeriesStyles(false); @@ -75,10 +75,10 @@ protected override void OnParametersSet() } } - if (_selectionPattern != SelectionPattern) + if (_selection.SelectionPattern != SelectionPattern) { - _selectionPattern = SelectionPattern; - _ = CallJSInteropForSelectionHighlightOptionAsync(); + _selection.SelectionPattern = SelectionPattern; + await CallJSInteropForSelectionHighlightOptionAsync(); if (_selectionModule is not null) { _selectionModule.CallSeriesStyles(); @@ -86,10 +86,10 @@ protected override void OnParametersSet() } } - if (_highlightMode != HighlightMode) + if (_selection.HighlightMode != HighlightMode) { - _highlightMode = HighlightMode; - _ = CallJSInteropForSelectionHighlightOptionAsync(_selectionModule is not null && _isScriptLoaded); + _selection.HighlightMode = HighlightMode; + await CallJSInteropForSelectionHighlightOptionAsync(_selectionModule is not null && _isScriptLoaded); if (_highlightModule is null && _isScriptLoaded) { _highlightModule = new Highlight(this) @@ -104,10 +104,10 @@ protected override void OnParametersSet() _highlightModule?.PropertyChanged(); } - if (_selectionMode != SelectionMode) + if (_selection.SelectionMode != SelectionMode) { - _selectionMode = SelectionMode; - _ = CallJSInteropForSelectionHighlightOptionAsync(_selectionModule is null && _isScriptLoaded); + _selection.SelectionMode = SelectionMode; + await CallJSInteropForSelectionHighlightOptionAsync(_selectionModule is null && _isScriptLoaded); if (_selectionModule is null && _isScriptLoaded) { _selectionModule = new Selection(this) @@ -121,57 +121,57 @@ protected override void OnParametersSet() _selectionModule?.ChartSelectionModeChanged(); } - if (_enableSideBySidePlacement != EnableSideBySidePlacement) + if (_layout.EnableSideBySidePlacement != EnableSideBySidePlacement) { - _enableSideBySidePlacement = EnableSideBySidePlacement; - _updateLayout = true; + _layout.EnableSideBySidePlacement = EnableSideBySidePlacement; + _layout.UpdateLayout = true; } - if (_theme != Theme) + if (_appearance.Theme != Theme) { - _theme = Theme; + _appearance.Theme = Theme; if (IsRendered) { - _chartThemeStyle = ChartHelper.GetChartThemeStyle(_theme.ToString()); + _chartThemeStyle = ChartHelper.GetChartThemeStyle(_appearance.Theme.ToString()); OnThemeChanged(); } } - if (_isTransposed != IsTransposed) + if (_layout.IsTransposed != IsTransposed) { - _isTransposed = IsTransposed; + _layout.IsTransposed = IsTransposed; if (IsRendered) { InitiAxis(); - _updateLayout = IsRendered; + _layout.UpdateLayout = IsRendered; } } - if (_subTitle != SubTitle) + if (_appearance.SubTitle != SubTitle) { - _subTitle = SubTitle; + _appearance.SubTitle = SubTitle; TitleChanged(); } - if (_title != Title) + if (_appearance.Title != Title) { - _title = Title; + _appearance.Title = Title; TitleChanged(); } - if (_width != Width) + if (_appearance.Width != Width) { - _width = Width; - _updateLayout = IsRendered; + _appearance.Width = Width; + _layout.UpdateLayout = IsRendered; } - if (_height != Height) + if (_appearance.Height != Height) { - _height = Height; - _updateLayout = IsRendered; + _appearance.Height = Height; + _layout.UpdateLayout = IsRendered; } - if (_background != Background) + if (_appearance.Background != Background) { - _background = Background; + _appearance.Background = Background; if (IsRendered && _chartBorderRenderer is not null) { _chartBorderRenderer.RendererShouldRender = true; @@ -179,23 +179,23 @@ protected override void OnParametersSet() } } - if (_highlightColor != HighlightColor) + if (_appearance.HighlightColor != HighlightColor) { - _highlightColor = HighlightColor; - _ = CallJSInteropForSelectionHighlightOptionAsync(); + _appearance.HighlightColor = HighlightColor; + await CallJSInteropForSelectionHighlightOptionAsync(); _highlightModule?.CallSeriesStyles(false); } - if (_dataSource != DataSource) + if (_data.DataSource != DataSource) { - _dataSource = DataSource; - if (_dataSource is INotifyCollectionChanged notifyCollectionChanged) + _data.DataSource = DataSource; + if (_data.DataSource is INotifyCollectionChanged notifyCollectionChanged) { notifyCollectionChanged.CollectionChanged += DataCollectionChanged; - if (_dataSource.Any() && _dataSource.First() is INotifyPropertyChanged) + if (_data.DataSource.Any() && _data.DataSource.First() is INotifyPropertyChanged) { - foreach (INotifyPropertyChanged item in _dataSource.Cast()) + foreach (INotifyPropertyChanged item in _data.DataSource.Cast()) { if (item is INotifyPropertyChanged notifyPropertyChanged) { @@ -206,14 +206,14 @@ protected override void OnParametersSet() } } - if (!_palettes.SequenceEqual(Palettes)) + if (!_appearance.Palettes.SequenceEqual(Palettes)) { if (Palettes is null) { return; } - _palettes = Palettes.Clone() as string[] ?? []; + _appearance.Palettes = Palettes.Clone() as string[] ?? []; } } @@ -240,7 +240,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) return; } await ImportComponentModuleAsync().ConfigureAwait(true); - if (!_isSizeSet) + if (!_render.IsSizeSet) { await HandleInitialRenderAsync(firstRender).ConfigureAwait(true); } @@ -289,16 +289,16 @@ protected override async ValueTask DisposeAsyncCore() { if (IsRendered) { - _ = UnWireEventsAsync(); + await UnWireEventsAsync(); _svgRenderer?.Dispose(); _pathAnimationElements?.Clear(); _textAnimationElements?.Clear(); _rectAnimationElements?.Clear(); _noDataTemplateContainer = null; - await DisposeJsModuleAsync(_svgJsModule, _svgJsInProcessModule).ConfigureAwait(false); - _svgJsModule = null; - _svgJsInProcessModule = null; + await DisposeJsModuleAsync(_interop.SvgJsModule, _interop.SvgJsInProcessModule).ConfigureAwait(false); + _interop.SvgJsModule = null; + _interop.SvgJsInProcessModule = null; await DisposeJsModuleAsync(_chartJsModule, _chartJsInProcessModule).ConfigureAwait(false); _chartJsModule = null; @@ -382,14 +382,14 @@ private async Task HandlePostRenderAsync(bool firstRender) UpdateClientSideScrollbar(); if (!firstRender && _isLegendRendered) { - _ = UpdateLegendTemplateAsync(); + await UpdateLegendTemplateAsync(); } if (_zoomingModule is not null && !string.IsNullOrEmpty(_zoomingKeyboardFocusTarget)) { await InvokeVoidAsync(_chartJsModule, _chartJsInProcessModule, Constants.FocusTarget, [_zoomingKeyboardFocusTarget]).ConfigureAwait(true); _zoomingKeyboardFocusTarget = string.Empty; } - if (!firstRender && _isSizeSet && _selectionModule is not null && SelectedDataIndexes.Count > 0) + if (!firstRender && _render.IsSizeSet && _selectionModule is not null && SelectedDataIndexes.Count > 0) { await _selectionModule.RemoveSelectedElementsAsync().ConfigureAwait(true); _selectionModule.InvokeSelection(); @@ -404,11 +404,11 @@ private async Task HandlePostRenderAsync(bool firstRender) JsModuleReference svgJsModuleReference = await ImportModuleAsync( "./_content/Syncfusion.Blazor.Toolkit/scripts/svgbase.js", - _svgJsModule, - _svgJsInProcessModule + _interop.SvgJsModule, + _interop.SvgJsInProcessModule ).ConfigureAwait(true); - _svgJsModule = svgJsModuleReference.AsyncRef; - _svgJsInProcessModule = svgJsModuleReference.InProcessRef; + _interop.SvgJsModule = svgJsModuleReference.AsyncRef; + _interop.SvgJsInProcessModule = svgJsModuleReference.InProcessRef; await LoadAnimationScriptAsync().ConfigureAwait(true); @@ -469,7 +469,7 @@ await InvokeVoidAsync(_chartJsModule!, _chartJsInProcessModule!, "initialize", [ if (_isLegendRendered) { - _ = UpdateLegendTemplateAsync(); + await UpdateLegendTemplateAsync(); } if (_tooltip.Enable || _crosshair.Enable || _markerExplode is not null) diff --git a/src/Components/Charts/Chart/SfChart.razor.Members.cs b/src/Components/Charts/Chart/SfChart.razor.Members.cs index dd28efe..6fdfc88 100644 --- a/src/Components/Charts/Chart/SfChart.razor.Members.cs +++ b/src/Components/Charts/Chart/SfChart.razor.Members.cs @@ -18,23 +18,43 @@ public partial class SfChart #region Fields - private string _highlightColor = null!; - private string _background = string.Empty; - private string _title = string.Empty; - private string _subTitle = string.Empty; - private string _height = DefaultHeight; - private string _width = DefaultWidth; - private string[] _palettes = []; - private bool _isMultiSelect; - private bool _isTransposed; - private bool _enableSideBySidePlacement = true; - private bool _updateLayout; - private HighlightMode _highlightMode; - private ChartSelectionMode _selectionMode; - private SelectionPattern _selectionPattern; - private SelectionPattern _highlightPattern; - private IEnumerable _dataSource = null!; - private Theme _theme = Theme.Fluent; + internal class AppearanceState + { + public string HighlightColor { get; set; } = null!; + public string Background { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public string SubTitle { get; set; } = string.Empty; + public string Height { get; set; } = DefaultHeight; + public string Width { get; set; } = DefaultWidth; + public string[] Palettes { get; set; } = []; + public Theme Theme { get; set; } = Theme.Fluent; + } + + internal class LayoutState + { + public bool IsTransposed { get; set; } + public bool EnableSideBySidePlacement { get; set; } = true; + public bool UpdateLayout { get; set; } + } + + internal class SelectionState + { + public bool IsMultiSelect { get; set; } + public HighlightMode HighlightMode { get; set; } + public ChartSelectionMode SelectionMode { get; set; } + public SelectionPattern SelectionPattern { get; set; } + public SelectionPattern HighlightPattern { get; set; } + } + + internal class ChartDataState + { + public IEnumerable DataSource { get; set; } = null!; + } + + private readonly AppearanceState _appearance = new(); + private readonly LayoutState _layout = new(); + private readonly SelectionState _selection = new(); + private readonly ChartDataState _data = new(); #endregion @@ -63,7 +83,7 @@ public partial class SfChart /// /// [Parameter] - public string Height { get; set; } = null!; + public string Height { get; set; } = DefaultHeight; /// /// Gets or sets the width of the chart as a string. @@ -542,7 +562,7 @@ private async Task CallJSInteropForSelectionHighlightOptionAsync(bool is_selecti await InvokeVoidAsync(_chartJsModule!, _chartJsInProcessModule!, Constants.SetHighlightSelectionOptions, [_dataId, GetSelectionHighlightOptions()]).ConfigureAwait(false); if (is_selectionModule) { - await InvokeVoidAsync(_chartJsModule!, _chartJsInProcessModule!, Constants.SelectDataIndex, [_dataId, _selectedDataIndexes?.ToArray() ?? []]).ConfigureAwait(false); + await InvokeVoidAsync(_chartJsModule!, _chartJsInProcessModule!, Constants.SelectDataIndex, [_dataId, _currentData.SelectedDataIndexes?.ToArray() ?? []]).ConfigureAwait(false); } } } diff --git a/src/Components/Charts/Chart/SfChart.razor.Methods.cs b/src/Components/Charts/Chart/SfChart.razor.Methods.cs index 3c58362..38cf273 100644 --- a/src/Components/Charts/Chart/SfChart.razor.Methods.cs +++ b/src/Components/Charts/Chart/SfChart.razor.Methods.cs @@ -8,20 +8,6 @@ public partial class SfChart { #region Public Methods - /// - /// The method is used to add the axes in chart. - /// - /// Specifies the chart axis collection. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static void AddAxes(List axisCollection) - { - if (axisCollection is null) - { - return; - } - } - /// /// The method is used to re-render the chart. /// @@ -383,7 +369,7 @@ public void ClearSort() /// public void ClearSelection() { - if (_selectionModule is not null && _selectionMode != ChartSelectionMode.None) + if (_selectionModule is not null && _selection.SelectionMode != ChartSelectionMode.None) { _selectionModule.PerformClearSelection(); } @@ -393,7 +379,7 @@ public void ClearSelection() /// Prevents the Chart render. This method will internally sets value to be returned from ShouldRender method. /// /// Default value is true. Once PreventRender(true) called, component won't re-render until PreventRender(false) called. - public void PreventRender(bool preventRender = true) => _shouldChartRender = !preventRender; + public void PreventRender(bool preventRender = true) => _render.ShouldChartRender = !preventRender; #endregion } diff --git a/src/Components/Charts/Chart/SfChart.razor.PointerEvents.cs b/src/Components/Charts/Chart/SfChart.razor.PointerEvents.cs index b131598..2a44e00 100644 --- a/src/Components/Charts/Chart/SfChart.razor.PointerEvents.cs +++ b/src/Components/Charts/Chart/SfChart.razor.PointerEvents.cs @@ -150,9 +150,9 @@ private async Task OnMouseDownAsync(ChartInternalMouseEventArgs args) await HandleLegendClickAsync(args).ConfigureAwait(true); } - if (!_isTouch && !_isLegendClick && (_previousMouseMoveReqTime == DateTime.MinValue || (DateTime.Now - _previousMouseMoveReqTime).TotalMilliseconds >= Constants.UpdateThersholdMs)) + if (!_isTouch && !_isLegendClick && (_interaction.PreviousMouseMoveReqTime == DateTime.MinValue || (DateTime.Now - _interaction.PreviousMouseMoveReqTime).TotalMilliseconds >= Constants.UpdateThersholdMs)) { - _previousMouseMoveReqTime = DateTime.Now; + _interaction.PreviousMouseMoveReqTime = DateTime.Now; _isLegendClick = true; } } diff --git a/src/Components/Charts/Chart/SfChart.razor.cs b/src/Components/Charts/Chart/SfChart.razor.cs index 7581ae9..dde34ab 100644 --- a/src/Components/Charts/Chart/SfChart.razor.cs +++ b/src/Components/Charts/Chart/SfChart.razor.cs @@ -36,19 +36,38 @@ public partial class SfChart : SfDataBoundComponent, ISubcomponentTracker #region Private Fields - private int _pendingParametersSetCount; - private string _svgCursor = "auto"; - private bool _shouldChartRender = true; - private bool _isSizeSet; - private bool _updateDataSource = true; - private Size _availableSize = new(600, 450); - private Rect? _initialRect; - private List? _selectedDataIndexes; - private DateTime _previousMouseMoveReqTime = DateTime.MinValue; - private DateTime _previousRequestTime = DateTime.MinValue; - - private IJSObjectReference? _svgJsModule; - private IJSInProcessObjectReference? _svgJsInProcessModule; + internal class InteractionState + { + public string SvgCursor { get; set; } = "auto"; + public DateTime PreviousMouseMoveReqTime { get; set; } = DateTime.MinValue; + } + + internal class RenderState + { + public bool ShouldChartRender { get; set; } = true; + public bool IsSizeSet { get; set; } + public Size AvailableSize { get; set; } = new(600, 450); + public Rect? InitialRect { get; set; } + } + + internal class DataState + { + public bool UpdateDataSource { get; set; } = true; + public List? SelectedDataIndexes { get; set; } + } + + internal class JsInteropState + { + public int PendingParametersSetCount { get; set; } + public DateTime PreviousRequestTime { get; set; } = DateTime.MinValue; + public IJSObjectReference? SvgJsModule { get; set; } + public IJSInProcessObjectReference? SvgJsInProcessModule { get; set; } + } + + private readonly InteractionState _interaction = new(); + private readonly RenderState _render = new(); + private readonly DataState _currentData = new(); + private readonly JsInteropState _interop = new(); #endregion @@ -240,13 +259,13 @@ public partial class SfChart : SfDataBoundComponent, ISubcomponentTracker /// internal Size AvailableSize { - get => _availableSize; + get => _render.AvailableSize; set { - if (_availableSize != value) + if (_render.AvailableSize != value) { - _availableSize = value; - _isSizeSet = true; + _render.AvailableSize = value; + _render.IsSizeSet = true; } } } @@ -256,13 +275,13 @@ internal Size AvailableSize /// internal Rect InitialRect { - get => _initialRect ?? null!; + get => _render.InitialRect ?? null!; set { - if (_initialRect != value) + if (_render.InitialRect != value) { - _initialRect = value; - _isSizeSet = true; + _render.InitialRect = value; + _render.IsSizeSet = true; } } } @@ -661,7 +680,7 @@ private async Task PerformDelayAnimationAsync() { if (_shouldAnimateSeries && !IsDisposed) { - _previousRequestTime = DateTime.Now; + _interop.PreviousRequestTime = DateTime.Now; await Task.Delay(UpdateThresholdMs).ConfigureAwait(true); List animationInfo = []; _seriesContainer?.PerformAnimation(animationInfo); @@ -678,8 +697,8 @@ private void PerformSelection() { if (_selectionModule is not null) { - _selectedDataIndexes = []; - _selectedDataIndexes = _selectionModule.SelectedDataIndexes.GetRange(0, _selectionModule.SelectedDataIndexes.Count); + _currentData.SelectedDataIndexes = []; + _currentData.SelectedDataIndexes = _selectionModule.SelectedDataIndexes.GetRange(0, _selectionModule.SelectedDataIndexes.Count); _selectionModule.InvokeSelection(); _selectionModule.AppendSelectionPattern(); @@ -691,9 +710,9 @@ private void PerformSelection() _highlightModule.AppendSelectionPattern(); } - if (_selectionModule is not null && _selectedDataIndexes?.Count > 0) + if (_selectionModule is not null && _currentData.SelectedDataIndexes?.Count > 0) { - _selectionModule.SelectedDataIndexes = _selectedDataIndexes.GetRange(0, _selectedDataIndexes.Count); + _selectionModule.SelectedDataIndexes = _currentData.SelectedDataIndexes.GetRange(0, _currentData.SelectedDataIndexes.Count); _ = _selectionModule.RedrawSelectionAsync(); } } @@ -974,7 +993,7 @@ private string GetSvgWidth() /// void ISubcomponentTracker.PushSubcomponent() { - _pendingParametersSetCount++; + _interop.PendingParametersSetCount++; } /// @@ -982,8 +1001,8 @@ void ISubcomponentTracker.PushSubcomponent() /// void ISubcomponentTracker.PopSubcomponent() { - _pendingParametersSetCount--; - if (_pendingParametersSetCount == 0) + _interop.PendingParametersSetCount--; + if (_interop.PendingParametersSetCount == 0) { RenderFrame(); } @@ -1286,10 +1305,10 @@ internal async Task PerformLayoutAsync() { _neededRenderers.Clear(); InitiAxis(); - if (_isSizeSet && _pendingParametersSetCount == 0) + if (_render.IsSizeSet && _interop.PendingParametersSetCount == 0) { ProcessData(); - await GetOtherLanguageCharSizeAsync(_updateDataSource).ConfigureAwait(true); + await GetOtherLanguageCharSizeAsync(_currentData.UpdateDataSource).ConfigureAwait(true); SetContainerSize(); Rect initialClipRect = InitialRect; @@ -1677,7 +1696,7 @@ internal void InitializeStaticChart() { try { - if (!_isSizeSet) + if (!_render.IsSizeSet) { CalculateAvailableSize(); SetInitialRect(); @@ -1763,9 +1782,9 @@ internal double GetChartMargin(bool isTopOrBottom = false) /// A task that represents the asynchronous operation. internal async Task PerformRedrawAnimationAsync() { - if (_redraw && !IsDisposed && (_previousRequestTime == DateTime.MinValue || (DateTime.Now - _previousRequestTime).TotalMilliseconds > UpdateThresholdMs)) + if (_redraw && !IsDisposed && (_interop.PreviousRequestTime == DateTime.MinValue || (DateTime.Now - _interop.PreviousRequestTime).TotalMilliseconds > UpdateThresholdMs)) { - _previousRequestTime = DateTime.Now; + _interop.PreviousRequestTime = DateTime.Now; await Task.Delay(UpdateThresholdMs).ConfigureAwait(true); _redraw = false; await InvokeVoidAsync(_chartJsModule!, _chartJsInProcessModule!, "doDynamicAnimation", [_pathAnimationElements.Values.ToArray(), _rectAnimationElements, _textAnimationElements.Values.ToArray(), _dynamicLastLabels]).ConfigureAwait(true); @@ -2015,9 +2034,9 @@ internal void AddTrendline(ChartTrendline trendline) internal async Task DelayLayoutChangeAsync(bool isZoom = false) { _isLayoutChange = true; - if (!IsDisposed && (_previousRequestTime == DateTime.MinValue || (DateTime.Now - _previousRequestTime).TotalMilliseconds > UpdateThresholdMs)) + if (!IsDisposed && (_interop.PreviousRequestTime == DateTime.MinValue || (DateTime.Now - _interop.PreviousRequestTime).TotalMilliseconds > UpdateThresholdMs)) { - _previousRequestTime = DateTime.Now; + _interop.PreviousRequestTime = DateTime.Now; await Task.Delay(UpdateThresholdMs).ConfigureAwait(true); if (isZoom && _zoomingModule is not null) { @@ -2041,7 +2060,7 @@ internal async Task DelayLayoutChangeAsync(bool isZoom = false) /// Whether to skip secondary element position calculation and tooltip updates. internal void OnLayoutChange(bool skip = false) { - if (_isSizeSet && _isChartFirstRender) + if (_render.IsSizeSet && _isChartFirstRender) { UpdateRenderers(skip); ApplyZoomkit(); @@ -2241,7 +2260,7 @@ internal void SetSvgCursor(string cursor, bool isKeyboardFocused = false) { return; } - _svgCursor = cursor; + _interaction.SvgCursor = cursor; _ = SetAttributeAsync(SvgId(), "cursor", cursor, isKeyboardFocused ? ID : string.Empty); } @@ -2295,9 +2314,9 @@ internal async Task ProcessOnLayoutChangeAsync() { const int UPDATETHRESHOLD = 10; _isLayoutChange = true; - if (!IsDisposed && IsRendered && (_previousRequestTime == DateTime.MinValue || (DateTime.Now - _previousRequestTime).TotalMilliseconds > UPDATETHRESHOLD)) + if (!IsDisposed && IsRendered && (_interop.PreviousRequestTime == DateTime.MinValue || (DateTime.Now - _interop.PreviousRequestTime).TotalMilliseconds > UPDATETHRESHOLD)) { - _previousRequestTime = DateTime.Now; + _interop.PreviousRequestTime = DateTime.Now; if (JSRuntime is not JSInProcessRuntime || !_isLiveChart) { await Task.Delay(UPDATETHRESHOLD).ConfigureAwait(true); @@ -2324,7 +2343,7 @@ internal async Task RefreshChartAsync() InitiAxis(); _seriesContainer?.InitSeriesRendererFields(); ProcessData(); - await GetOtherLanguageCharSizeAsync(_updateDataSource).ConfigureAwait(true); + await GetOtherLanguageCharSizeAsync(_currentData.UpdateDataSource).ConfigureAwait(true); _isRefreshed = true; UpdateRenderers(); PerformSelection(); diff --git a/src/wwwroot/scripts/chart.js b/src/wwwroot/scripts/chart.js index dfa7d44..458ed35 100644 --- a/src/wwwroot/scripts/chart.js +++ b/src/wwwroot/scripts/chart.js @@ -1147,7 +1147,10 @@ const SfChart = (function () { this.currentSeriesIndex = seriesIndexes.indexOf(this.currentSeriesIndex) + (e.code === 'ArrowRight' ? 1 : -1); this.currentSeriesIndex = seriesIndexes[getActualIndex(this.currentSeriesIndex, seriesIndexes.length)]; currentSeries = getCurrentSeries(this, targetId, this.currentSeriesIndex); - while (!currentSeries.focusable) { + const maxAttempts = seriesIndexes.length; + let attempts = 0; + while ((!currentSeries || !currentSeries.focusable || !currentSeries.visible || + currentSeries.index !== this.currentSeriesIndex) && attempts < maxAttempts) { this.currentSeriesIndex = seriesIndexes.indexOf(this.currentSeriesIndex) + (e.code === 'ArrowRight' ? 1 : -1); this.currentSeriesIndex = seriesIndexes[getActualIndex(this.currentSeriesIndex, seriesIndexes.length)]; currentSeries = getCurrentSeries(this, targetId, this.currentSeriesIndex); @@ -2539,6 +2542,13 @@ export function getCurrentSeries(chart, targetId, seriesIndex) { currentSeries = series; } }); + if (sfBlazorToolkit.base.isNullOrUndefined(currentSeries)) { + targetSeries.forEach((series) => { + if (series.focusable && series.visible && series.type.indexOf("Stacking") > -1) { + currentSeries = series; + } + }); + } return currentSeries; }