Pre loader

Tag: MVVM

Welcome to the SciChart Forums!

  • Please read our Question Asking Guidelines for how to format a good question
  • Some reputation is required to post answers. Get up-voted to avoid the spam filter!
  • We welcome community answers and upvotes. Every Q&A improves SciChart for everyone

WPF Forums | JavaScript Forums | Android Forums | iOS Forums

0 votes
3k views

Hi,

I’m trying to evaluate the reality of creating multiple realtime charts and I’m hitting a huge performance brick wall.

My application will have high speed streamed data coming in over ethernet. Currently I’m simulating this with a thread timer that updates 100 data objects at 60Hz. Screen data and chart updates I’ve got throttled to 30Hz but it’s still grinding my charts are still struggling. If I move the mouse pointer the charts freeze entirely until the mouse is still.

I want the end user to be able to choose any data object and chart it however they want. Adding charts and adding plots to charts etc. To enable this I’ve created a chart template as a user control and at runtime the charts are added to a panel on a tab control. Event one chart on one tab chugs though. Move the mouse over it and it locks up.

I have a single overview chart with a scrollbar over the top on the parent control. I need this to control the cursor (vertical line) and shared X visible range. Live data is Fifo limited to a 10 second range. All this works, just painfully slowly.

SharedXVisible range is MVVM bound. Renderable series is LineRenderableSeriesViewModel and data is pushed at 30Hz from a Data provider as per this tutorial:
https://www.scichart.com/documentation/win/current/Tutorial%2006b%20-%20Adding%20Realtime%20Updates%20with%20MVVM.html

CPU usage is sub 20%. Max frame rate is 30fps. Render priority doesn’t seem to make much difference, though “immediate” will lock up the whole app. I’m no expert at performance profiling but I’m not getting any clues from ReShaper dotTrace so far.

I tried creating a version that hand almost no binding and used codebehind to update the data. It didn’t seem to help. I’d rather not do this though as I have a lot of things working that I like such as vertical slice, annotations, templates etc.

I’ve got a list of all the live data on the right of the screen and it all updates rapidly, even while the mouse is moving and the charts are frozen.

I’m also using some Syncfusion controls and theming, if it matters.

I must be missing something obvious surely.

<!--  Define Chart  -->
        <s:SciChartSurface x:Name="chart" Grid.Row="0" Grid.Column="0"
                           Background="Black"
                           RenderPriority="low"
                           MaxFrameRate="30"
                           RenderableSeries="{s:SeriesBinding RenderableSeriesCollection}"
                           >

            <!--  Define X and Y Axis  -->
            <s:SciChartSurface.YAxis>
                <s:NumericAxis AutoRange="{Binding AxisYRangeMode}" 
                               DrawMajorBands="False" 
                               DrawMinorGridLines="false" 
                               DrawMajorGridLines="True" 
                               DrawMajorTicks="False" 
                               DrawMinorTicks="False" 
                               VisibleRange="{Binding AxisYVisibleRange}" />
            </s:SciChartSurface.YAxis>

            <s:SciChartSurface.XAxis>
                <s:NumericAxis AutoRange="{Binding AxisXRangeMode}" 
                               BorderBrush="{StaticResource BorderBrushGray}" 
                               BorderThickness="1" 
                               DrawMajorBands="False" 
                               DrawMinorGridLines="False" 
                               DrawMajorGridLines="True" 
                               DrawMajorTicks="False" 
                               DrawMinorTicks="False" 
                               TextFormatting="0" 
                               VisibleRange="{Binding SharedXVisibleRange, Mode=TwoWay}" 
                               s:VerticalSliceModifier.AxisLabelContainerStyle="{x:Null}"/>
            </s:SciChartSurface.XAxis>

            <!--  Modifiers  -->
            <s:SciChartSurface.ChartModifier>
                <s:ModifierGroup>
                    <s:RubberBandXyZoomModifier 
                        IsXAxisOnly="True" 
                        ZoomExtentsY="True" 
                        IsAnimated="True" 
                        RubberBandFill="#20FFFFFF" 
                        RubberBandStroke="GreenYellow" 
                        RubberBandStrokeDashArray="2 2">
                    </s:RubberBandXyZoomModifier>

                    <s:ZoomExtentsModifier IsAnimated="True"/>

                    <s:MouseWheelZoomModifier IsEnabled="True"/>

                    <s:XAxisDragModifier IsEnabled="True" DragMode="Pan"/>

                    <s:LegendModifier x:Name="legendModifier"
                                      Background="Transparent" 
                                      Margin="10" 
                                      GetLegendDataFor="AllSeries" 
                                      LegendItemTemplate="{StaticResource CustomLegendTemplate}" 
                                      ShowLegend="True" ShowVisibilityCheckboxes="True"/>

                    <s:VerticalSliceModifier Name="sliceModifier">

                    <s:VerticalSliceModifier.VerticalLines>
                            <s:VerticalLineAnnotation Style="{StaticResource sliceStyle}" 
                                                      X1="{Binding SlicePosition, Mode=TwoWay}"/>
                        </s:VerticalSliceModifier.VerticalLines>
                    </s:VerticalSliceModifier>

                </s:ModifierGroup>
            </s:SciChartSurface.ChartModifier>
        </s:SciChartSurface>

Thanks in advance,
Declan.

PS. I’m trying to attach a screenshot but it keeps saying “Forbidden”.

0 votes
8k views

Hi! I have problems with visible range managing of a polar plot

The code in xaml:

<s:SciChartSurface graphModule:PlotLengthHelper.PlotLength="{Binding PlotLength, Mode=OneWayToSource,   UpdateSourceTrigger=PropertyChanged}" 
                       x:Name="ChartSurface"
                       SizeChanged="ChartSurface_OnSizeChanged"
                        ChartTitle="{Binding ChartTitle}"
                       s:ThemeManager.Theme="BrightSpark"
                        Annotations="{s:AnnotationsBinding Annotations}"
                       RenderableSeries="{s:SeriesBinding Series}"
                       XAxes="{s:AxesBinding XAxes}"
                       YAxes="{s:AxesBinding YAxes}"

First example. The code of the axis:

    var yAxis = new PolarYAxisViewModel {AutoRange = AutoRange.Never};
    YAxes.Add(yAxis);

Changing the VisibleRange of the axis has no any effect on the visible range of the graph. It sets automatically in the very first time and remains the same.

Second example.

    var yAxis = new PolarYAxisViewModel {AutoRange = AutoRange.Always};
    YAxes.Add(yAxis);

Changing the data (using line series) again has no any effect on the visible range of the graph. Again, it sets automatically in the very first time and remains the same.

Any suggestion on how to fix it? Especially the first case is required. Thanks.

0 votes
8k views

When I select a series/plot, I would like to identify where it came with more than just the Name member. How can I do that?

Background:
I have a list of unsigned integer values taken from a data logger. I bundle the values up in a class with some other information, such as the name of the sample and an ID string.

Since I can’t data bind to the logged samples as-is, I convert them to a SciChart friendly “LineRenderableSeriesViewModel” and add them to a list of “ObservableCollection” that I data bind to a SciChart.

ViewModel.cs:

// Where "loggedSamples" is a SamplesContainer 
//class SamplesContainer
//{
//    public string Name;
//    public string ID;  **<=== I want to get this somehow when I select something**
//    public Uint16 data {get;set;}
//}

// Convert Samples => XyDataSeries => LineRenderableSeriesViewModel

SamplesContainer loggedSamples = GetLoggedSample();
XyDataSeries<double, double> xySeries = ConvertSamplesToXyDataSeries(loggedSamples);
xySeries.SeriesName = loggedSamples.Name;

LineRenderableSeriesViewModel lineSeries = new LineRenderableSeriesViewModel() {
    DataSeries = xySeries, StyleKey = "LineStyle", Stroke = Colors.Blue };

RenderableSeriesViewModelForChannels.Add(lineSeries);

MainWindow.xaml:

   <s:SciChartSurface Name="sciChartItemView" Grid.Column="2"
    AllowDrop="True"
    DragDrop.Drop="sciChartItemView_Drop"
    DragDrop.DragEnter="sciChartItemView_DragEnter"
    MinHeight="80"
    s:ThemeManager.Theme="BrightSpark"  
    RenderableSeries="{s:SeriesBinding RenderableSeriesViewModelForChannels}"
    ViewportManager="{Binding SampleSetViewMod.ViewportManager}"                                                                           
    DebugWhyDoesntSciChartRender="True"
    s:SciChartGroup.VerticalChartGroup="sharedYAxisWidth"
    >

    <s:SciChartSurface.XAxis>
        <s:NumericAxis   
        DrawMajorGridLines="True"
        DrawMinorGridLines="False"
        DrawMajorBands="False"  
        VisibleRange="{Binding SampleSetViewMod.SharedXVisibleRange, Mode=TwoWay}"
        Visibility="Hidden" 
        TextFormatting="0.######"/>
    </s:SciChartSurface.XAxis>

    <s:SciChartSurface.YAxis>
        <s:NumericAxis AxisAlignment="Left"
        DrawMajorGridLines="False"
        DrawMinorGridLines="False"
        DrawMajorBands="False"
        Visibility="Visible">
            <s:NumericAxis.GrowBy>
                <s:DoubleRange Min="0.1" Max="0.1" />
            </s:NumericAxis.GrowBy>
        </s:NumericAxis>

    </s:SciChartSurface.YAxis>

    <s:SciChartSurface.ChartModifier>
        <s:ModifierGroup>
            <s:ZoomExtentsModifier XyDirection="YDirection"/>

            <s:ZoomPanModifier ExecuteOn="MouseMiddleButton" XyDirection="XYDirection" ClipModeX="ClipAtExtents" />

            <local:ExtendedMouseWheelZoomModifier />

            <s:RubberBandXyZoomModifier IsEnabled="True"
                IsXAxisOnly="False"
                ReceiveHandledEvents="True" />
            <s:LegendModifier ShowLegend="True" Orientation="Vertical" Margin="10"
                GetLegendDataFor="AllSeries"
                ShowVisibilityCheckboxes="False" 
                HorizontalAlignment="Right"
                LegendPlacement="Inside"
                Background="White"
                />

            <local:ExtendedSeriesSelectionModifier SelectionChanged="SeriesSelectionModifier_OnSelectionChanged">
                <local:ExtendedSeriesSelectionModifier.SelectedSeriesStyle>
                    <Style TargetType="s:FastLineRenderableSeriesForMvvm">
                        <Setter Property="StrokeDashArray" Value="10,5"/>
                    </Style>
                </local:ExtendedSeriesSelectionModifier.SelectedSeriesStyle>
            </local:ExtendedSeriesSelectionModifier>


            <!--<s:CursorModifier x:Name="cursorModifier" IsEnabled="True" />
        <s:RolloverModifier x:Name="rolloverModifier" IsEnabled="True"/>-->
        </s:ModifierGroup>
    </s:SciChartSurface.ChartModifier>
</s:SciChartSurface>
1 vote
3k views

Hello,
I’m using SciChart in our WPF project. And we are Keeping Series and Annotations as RadObservableCollection(from Telerik) instead of ObservableCollection to get the benefits of RadObservableCollection. But when I’m adding or deleting data from RadObservableCollection it does not affect in charts. Does SciChart work with RadObservableCollection ? I’ve explored your examples and wasn’t able to found examples with RadObservableCollection.

1 vote
3k views

Hello.
I’m just started to use SciChart and I have a question. How I can mirror XAxis in order to values will be increased from right to left. It is not negative scale but this view is more familiar for users (now I remake the old application). P.S. And be the best if additionally you show me how to make static XAxis with chosen range. I see the example in demo’s “Create Realtime Charts” section (my chart will be real-time too), but my application created via MVVM and I think this example not fully applicable to my case (but I fink after some investigation I will can remake example, but if you help me it be easier).

0 votes
8k views

Hi there,

I am relatively new to C# and scicharts so you will have to forgive me a little.

In the project I am working on, I am trying to add dynamic renderable series as the user selects items in a tree. I have looked through the online tutorials and forums but still am having trouble. I am creating my own renderable series view model class derived off of LineRenderableSeriesViewModel. I found documentation that I needed to override the ViewType property and set it to a FastLineRenderableSeriesForMvvm.

When I am creating these objects to add to the ObservableCollection which is bound to my scichart surface, I can set the PointMarker and its properties, but not the SelectedPointMarker properties.

XAML:

    <s:SciChartSurface Style="{StaticResource BasicSciChartSurfaceStyleRateVsTime}"
                       ViewportManager="{Binding RateVsTimePlot.Manipulator.Viewport}"
                       Name="RateVsTime" x:FieldModifier="private"
                       ZoomHistoryManager="{Binding RateVsTimePlot.ZoomHistory}"
                       PreviewMouseLeftButtonDown="PreviewRateVsTimeMouseLeftButtonDown"
                       PreviewMouseLeftButtonUp="PreviewRateVsTimeMouseLeftButtonUp"
                       RenderableSeries="{s:SeriesBinding RateVsTimePlot.RenderableSeriesViewModels}"
                       local:YAxesCollectionBehaviour.AxisSource="{Binding RateVsTimePlot.YAxesViewModels}"
                       local:YAxesCollectionBehaviour.AxisStyle="{StaticResource AxisStyle}"/>         

Style:

<Style x:Key="ProdLineStyle" TargetType="s:FastLineRenderableSeriesForMvvm">
    <Setter Property="s:TooltipModifier.IncludeSeries" Value="False"/>
    <Setter Property="SelectedPointMarker">
        <Setter.Value>
            <s:EllipsePointMarker Fill="{Binding SeriesColors.ProductionColor}"
                                  Stroke="{Binding SeriesColors.ProductionColor}"
                                  Width="6" Height="6">
            </s:EllipsePointMarker>
        </Setter.Value>
     </Setter>
</Style>

ViewModel :

        var renderableSeries = new GenericRenderableSeriesViewModel
        {
            DataSeries = dataSeries.DataSeries,
            YAxisId = dataSeries.AxisId,
            IsSelected = IsSelected,
            SeriesColors = _dataColors[fluidRateType],
            DisplayEnabled = AnalysisInteractionMode.IsLineManipulationDisabled,
            PointMarker = new EllipsePointMarker(),
            StyleKey = "ProdLineStyle"
        };

        renderableSeries.SetRenderableSeriesColorSettings();

        renderableSeries.DataSeries.SeriesName = fluidRateType.ToString();
        return renderableSeries;

public void SetRenderableSeriesColorSettings()
    {
        Stroke = SeriesColors.ProductionColor;

        if (PointMarker == null) return;

        PointMarker.Stroke = SeriesColors.ProductionColor;
        PointMarker.Fill = SeriesColors.ProductionColor;
        PointMarker.Height = PointNonSelectedHeight;
        PointMarker.Width = PointNonSelectedWidth;
    }

When I run my app, I see what I am expecting by default, but when I do a point selection rectangle, the behavior is not correct. I only see the line. The points with in the rectangle disappear.

I am trying to move away from having the style set the selectedPointMarker, and doing it through code in the view model just like the function above as users will be able to change these properties in the future. But so far I haven’t found a way to do either.

Am I using the correct classes, or do I need to override something else? Any ideas or suggestions would be greatly appreciated

Thanks
Rylan

0 votes
12k views

Hi,
I’m prototyping an application with two visible data series and an individual Y-axis for each data series. See the enclosed image.
The Stroke color of each data series, the TickTextBrush and the BorderBrush of the y-axis are updated by normal data Binding through the MVVM pattern.
The problem is that I am not able to data bind the Stroke property of the MajorTickLineStyle for the individual Y-axis.
Do You know if there is a workaround for this through data binding?
The project is enclosed.

  • andreasrep asked 7 years ago
  • last active 7 years ago
0 votes
9k views

Hello!

I am getting started with SciChart and attempting to use it for a project I’m working on.

I am attempting to make a 3D scatter plot whose data is populated through a ViewModel.

Below is a my xaml:

 <UserControl x:Class="CustomWindow.Pages.Results_Page.Common_Tests.Positional6DOFErrorTest"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:enum="clr-namespace:MultiMet.Interfaces.Common;assembly=MultiMet.Interfaces"
             xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
             xmlns:s3D="http://schemas.abtsoftware.co.uk/scichart3D"
             mc:Ignorable="d" 
             d:DesignHeight="360" d:DesignWidth="712">

    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!-- Some other stuff I'm doing on the page -->

        <s3D:SciChart3DSurface Grid.Column="1" ShowLicensingWarnings="True"
                        IsFpsCounterVisible="False"
                         IsAxisCubeVisible="True"
                         IsXyzGizmoVisible="False"
                         CoordinateSystem="RightHanded"
                               Background="White" RenderableSeries="{s3D:SeriesBinding RenderableSeries3DViewModels}">
            <!-- Create XAxis -->
            <s3D:SciChart3DSurface.XAxis>
                <s3D:NumericAxis3D TickTextBrush="Black" AxisTitle="X (mm)" DrawMajorBands="True" DrawMajorGridLines="True"
                        DrawMinorGridLines="True"
                        DrawMajorTicks="True"
                        DrawMinorTicks="True"
                        AxisBandsFill="Transparent"
                        FontSize="10"
                        TickLabelAlignment="Camera"
                                   GrowBy="0.1, 0.1"/>
            </s3D:SciChart3DSurface.XAxis>
            <!-- Create YAxis -->
            <s3D:SciChart3DSurface.YAxis>
                <s3D:NumericAxis3D AxisTitle="Z (mm)"
                        AxisBandsFill="Transparent"
                        TickTextBrush="Black"
                        FontSize="10"
                        TickLabelAlignment="Camera"
                                   GrowBy="0.1, 0.1"/>
            </s3D:SciChart3DSurface.YAxis>
            <!-- Create ZAxis -->
            <s3D:SciChart3DSurface.ZAxis>
                <s3D:NumericAxis3D AxisTitle="Y (mm)"
                        AxisBandsFill="Transparent"
                        TickTextBrush="Black"
                        FontSize="10"
                        TickLabelAlignment="Camera"
                                   GrowBy="0.1, 0.1"/>
            </s3D:SciChart3DSurface.ZAxis>

            <!-- Create Interactivity Modifiers for rotating camera -->
            <s3D:SciChart3DSurface.ChartModifier>
                <s3D:ModifierGroup3D>
                    <s3D:OrbitModifier3D ExecuteOn="MouseLeftButton" ExecuteWhen="None"/>
                    <s3D:MouseWheelZoomModifier3D MouseWheelSensitivity="90" />
                    <s3D:FreeLookModifier3D ExecuteOn="MouseRightButton"/>
                    <s3D:TooltipModifier3D IsEnabled="True" SourceMode="AllSeries" ShowTooltipOn="MouseOver"/>
                </s3D:ModifierGroup3D>
            </s3D:SciChart3DSurface.ChartModifier>
        </s3D:SciChart3DSurface>
    </Grid>
</UserControl>

And below I declare and define my scatter plot in the viewmodel (the scatterSeries is an XyzDataSeries3D set somewhere else) :

    PositionalErrorTestModel.RenderSeries3DViewModels = new ObservableCollection<IRenderableSeries3DViewModel>();
PositionalErrorTestModel.RenderSeries3DViewModels.Add(new ScatterRenderableSeries3DViewModel
            {
                PointMarker = new SpherePointMarker3D { Fill = System.Windows.Media.Color.FromRgb(0x78, 0xC3, 0), Size = 5, Opacity = 1 },
                DataSeries = scatterSeries
            });

The chart appears, but the data does not. Is there something I’m missing? Do I need to explicitly call an update to the chart? Because the page the chart is on and the chart does get loaded before the data is populated.

Please let me know if you need to know anymore information.

Thanks for any help you can provide!

1 vote
18k views

We keep getting asked What’s the best practice way to suspend the SciChartSurface in a multi-pane stock chart demo.

We have multiple ways of doing this.

By far the most effective and thread-safe way to do this is to call SuspendUpdates directly on the SciChartSurface. But how to do this in a ViewModel?

1 vote
8k views

Hi there,

We are looking for a high-performance charting library, hence Im testing scichart and I am very excited about it.

Our application has an very abstract processing mechanism which categorize incoming data and dynamically adds channels to the plot. Each sample is – like we call it – a ProcessedData object which is a base class containing extented information about the sample like “is valid” or “is out of range”. Eg. if measureing a voltage, we need to mark data points on the chart that are “out of range” or similar.
I’d thought to start with the “DragHorizontalThreshold” which uses the RedIfOverThresholdPaletteProvider to change the color of the plot.
Do you have an idea if it is possible to implement a custom PaletteProvider which takes respect of an IsValid-property? Acutally i do not have a clue how to.

Thanks.

  • Sven Fink asked 9 years ago
  • last active 9 years ago
0 votes
5k views

Hi
I’m trying to use AvaloniaUI with .NET Core 3.1 to create an application using SciChart, but I get XAMLIL error when trying to add a SciChartSurface following the code from the tutorial. I used a standard Avalonia MVVM Application template when creating the project.

This is the code:

<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
             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"
             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
             x:Class="FF_DataVis_Avalonia_MVVM.Views.TabControlView">

    <Grid>
        <!-- Bind to ChartViewModel.ChartTitle etc -->
        <s:SciChartSurface ChartTitle="{Binding ChartTitle}">
            <s:SciChartSurface.XAxis>
                <s:NumericAxis AxisTitle="{Binding XAxisTitle}"/>
            </s:SciChartSurface.XAxis>
            <s:SciChartSurface.YAxis>
                <s:NumericAxis AxisTitle="{Binding YAxisTitle}"/>
            </s:SciChartSurface.YAxis>
        </s:SciChartSurface>
    </Grid>
</UserControl>

And the error I get is:
“XAMLIL: Unable to resolve type SciChartSurface from namespace http://schemas.abtsoftware.co.uk/scichart Line 27, position 4″
which is the first s:SciChartSurface entry.

Any ideas what might be wrong? Does SciChart not work with any framework regardless of using .NET Core 3.0?
I have tried changing between Core 3.0 and 3.1, which does nothing.

1 vote
18k views

I am using the MVVM pattern.

I trying to manage the number of YAxes in my chart in a dynamic manner by binding the YAxes in the chart to a collection so that each time I add a new line series that line series gets its own axis.

When I do this I am getting a null reference expection.
If I hard code the YAxes or YAxis my chart loads.

Here is the xaml:

<SciChart:SciChartSurface x:Name="historicalChart" 
    RenderableSeries="{Binding HistoricalRenderableSeries, Mode=TwoWay}"
    YAxes="{Binding ChartYAxes, Mode=TwoWay}"
    SciChart:ThemeManager.Theme="ExpressionLight">
   ...
</s:SciChartSurface>

Here is the ViewModel

I tried both an ObservableCollection and a AxisCollection in my view model.

private ObservableCollection<NumericAxis> _chartYAxes = new ObservableCollection<NumericAxis>();
public ObservableCollection<NumericAxis> ChartYAxes
{
  get { return _chartYAxes; }
  set
  {
    _chartYAxes = value;
    NotifyPropertyChanged("ChartYAxes");
  }
}

private AxisCollection _chartYAxes = new AxisCollection();
public AxisCollection ChartYAxes
{
  get { return _chartYAxes; }
  set
  {
    _chartYAxes = value;
    NotifyPropertyChanged("ChartYAxes");
  }
}

Can anyone suggest a way to manage a variable number of YAxes in a chart?

  • sdemooy asked 12 years ago
  • last active 9 years ago
1 vote
6k views

Hi, Support team.

I’m using MVVM pattern and trying to implement multi-chart which can insert Box Annotations at the same time into each chart .
So I’m testing in SciChart Example [“DigitalAnalyzerPerformanceDemo”] to know how to implement this.

But what i only got is just looping through and create annotation for each ChannelViewModels.

In the Demo, the VisibleRange ‘XRange’ is shared to all the ChannelViewModels by binding TwoWay-mode in ParentViewModel without looping for each ChildViewModels.
Like this, I wonder is there ways to apply BoxAnnotation all the ChannelViewModel at the same time by binding in ParentViewModel.

    <!-- BottomAxis -->
        <s:SciChartSurface Grid.Column="1">
            <s:SciChartSurface.XAxis>
                <s:NumericAxis Height="30"
                               AxisAlignment="Bottom"
                               VisibleRange="{Binding XRange, Mode=TwoWay}"                 
                               LabelProvider="{StaticResource TimeLabelProvider}"
                               MajorTickLineStyle="{StaticResource TimeAxisMajorTickLineStyle}"
                               MinorTickLineStyle="{StaticResource TimeAxisMinorTickLineStyle}"/>
            </s:SciChartSurface.XAxis>
            <s:SciChartSurface.YAxis>
                <s:NumericAxis Visibility="Collapsed"/>
            </s:SciChartSurface.YAxis>
        </s:SciChartSurface>
    </Grid>

    <!--  Create an X Axis with GrowBy  -->
     <s:SciChartSurface.XAxis>
           <s:NumericAxis Style="{StaticResource HiddenAxisStyle}"
                    VisibleRangeLimitMode="Min"
                    VisibleRangeLimit="0,0"
                    VisibleRange="{Binding DataContext.XRange, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=ItemsControl, AncestorLevel=2}}"/>
     </s:SciChartSurface.XAxis>

I tried to bind annotation in ParentViewModel like XRange Binding method, But it doesn’t work.


This is View.xaml.

<Grid Grid.IsSharedSizeScope="True" IsEnabled="{Binding IsLoading, Converter={StaticResource InvertBooleanConverter}}">


    <!-- BottomAxis -->
        <s:SciChartSurface Grid.Column="1">
            <s:SciChartSurface.XAxis>
                <s:NumericAxis Height="30"
                               AxisAlignment="Bottom"
                               VisibleRange="{Binding XRange, Mode=TwoWay}"                 
                               LabelProvider="{StaticResource TimeLabelProvider}"
                               MajorTickLineStyle="{StaticResource TimeAxisMajorTickLineStyle}"
                               MinorTickLineStyle="{StaticResource TimeAxisMinorTickLineStyle}"/>
            </s:SciChartSurface.XAxis>
            <s:SciChartSurface.YAxis>
                <s:NumericAxis Visibility="Collapsed"/>
            </s:SciChartSurface.YAxis>
        </s:SciChartSurface>
    </Grid>

    <!-- Channels -->
        <ScrollViewer Background="#1C1C1E"
                      VerticalScrollBarVisibility="Auto"
                      HorizontalScrollBarVisibility="Disabled">

            <b:Interaction.Behaviors>
                <common:DigitalAnalyzerScrollBehavior ChannelHeightDelta="10" ChangeChannelHeightCommand="{Binding ChangeChannelHeightCommand}"/>
            </b:Interaction.Behaviors>

            <ItemsControl x:Name="chartItemsControl" ItemsSource="{Binding ChannelViewModels}">

                <b:Interaction.Behaviors>
                    <common:FocusedChannelScrollBehavior ScrollToFocusedChannel="False"/>
                </b:Interaction.Behaviors>

                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type local:ChannelViewModel}">
                        <Grid Background="#2D2C32" Height="{Binding ChannelHeight, Mode=OneWay}" Focusable="False" UseLayoutRounding="False" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="ChannelNames" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>

                            <Border BorderThickness="0,0,0,1" BorderBrush="#1C1C1E">
                                <DockPanel>
                                    <Border DockPanel.Dock="Left"     
                                            Background="{Binding ChannelColor, Mode=OneWay}" 
                                            Width="5"/>

                                    <TextBlock DockPanel.Dock="Left"
                                               Margin="10,5"
                                               VerticalAlignment="Center"
                                               Foreground="White"
                                               Text="{Binding ChannelName}"/>
                                </DockPanel>
                            </Border>

                            <s:SciChartSurface x:Name="channelSurface" Grid.Column="1"
                                               RenderableSeries="{Binding RenderableSeries}"
                                               Annotations="{s:AnnotationsBinding  DataContext.Annotations, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=ItemsControl, AncestorLevel=2} }">

                                <!--  Create an X Axis with GrowBy  -->
                                <s:SciChartSurface.XAxis>
                                    <s:NumericAxis Style="{StaticResource HiddenAxisStyle}"
                                                   VisibleRangeLimitMode="Min"
                                                   VisibleRangeLimit="0,0"
                                                   VisibleRange="{Binding DataContext.XRange, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=ItemsControl, AncestorLevel=2}}"/>
                                </s:SciChartSurface.XAxis>

                                <!--  Create a Y Axis with GrowBy. Optional bands give a cool look and feel for minimal performance impact  -->
                                <s:SciChartSurface.YAxis>
                                    <s:NumericAxis Style="{StaticResource HiddenAxisStyle}"
                                                   VisibleRange="{Binding YRange, Mode=OneWay}"/>
                                </s:SciChartSurface.YAxis>

                                <s:SciChartSurface.ChartModifier>
                                    <s:ModifierGroup s:MouseManager.MouseEventGroup="ChannelModifierGroup">
                                        <s:RubberBandXyZoomModifier IsAnimated="False" IsXAxisOnly="True" ZoomExtentsY="False" ReceiveHandledEvents="True" IsEnabled="{Binding IsChecked, Mode=OneWay, ElementName=IsZoomEnabled}"/>
                                        <s:ZoomPanModifier ZoomExtentsY="False" XyDirection="XDirection" IsEnabled="{Binding IsChecked, Mode=OneWay, ElementName=IsPanEnabled}"/>
                                        <s:ZoomExtentsModifier XyDirection="XDirection" IsAnimated="False" />
                                        <s:MouseWheelZoomModifier XyDirection="XDirection" />
                                    </s:ModifierGroup>
                                </s:SciChartSurface.ChartModifier>
                            </s:SciChartSurface>

                            <Border Grid.Column="1"
                                    BorderThickness="0,0,0,1"
                                    BorderBrush="#2D2C32"
                                    VerticalAlignment="Bottom"/>
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Border>


</Grid>

This is ViewModel.cs

public class DigitalAnalyzerExampleViewModel : BaseViewModel
{
    private bool _isLoading;
    private DoubleRange _xRange;

    public DigitalAnalyzerExampleViewModel()
    {
        ChannelViewModels = new ObservableCollection<ChannelViewModel>();
        Annotations = new ObservableCollection<IAnnotationViewModel>();
        Annotations.Add(new BoxAnnotationViewModel() { X1 = 0, X2 = 1000, Y1 = 0, Y2 = 1 }); //I want to implement sharing annotation like this.

        SelectedChannelType = "Digital";
        SelectedChannelCount = 32;
        SelectedPointCount = 1000000;
        SelectedResamplingPrecision =ResamplingPrecision.Default;
        SelectedStrokeThickness = 1;

        ChangeChannelHeightCommand = new ActionCommand<object>((d) =>
        {
            var delta = (double)d;
            foreach (var channelViewModel in ChannelViewModels)
            {
                channelViewModel.SetChannelHeightDelta(delta);
            }
        });

        AddChannelCommand = new ActionCommand(async () =>
        {
            IsLoading = true;

            var isDigital = SelectedChannelType == "Digital";
            await AddChannels(isDigital ? 1 : 0, isDigital ? 0 : 1);

            IsLoading = false;
        });

        LoadChannelsCommand = new ActionCommand(async () =>
        {
            IsLoading = true;

            // Clear ViewModels
            foreach (var channelVm in ChannelViewModels)
            {
                channelVm.Clear();
            }
            ChannelViewModels.Clear();
            XRange = null;

            // Create a bunch of Digital channels
            await AddChannels(SelectedChannelCount, 0);

            XRange = new DoubleRange(0, SelectedPointCount);
            IsLoading = false;
        });

        LoadChannelsCommand.Execute(null);
    }


    public ObservableCollection<ChannelViewModel> ChannelViewModels { get; private set; }
    public ObservableCollection<IAnnotationViewModel> Annotations { get; private set; }

    public string SelectedChannelType { get; set; }


    public ResamplingPrecision SelectedResamplingPrecision { get; set; }

    public int SelectedChannelCount { get; set; }

    public ActionCommand<object> ChangeChannelHeightCommand { get; }

    public ActionCommand AddChannelCommand { get; }

    public ActionCommand LoadChannelsCommand { get; }

    public long TotalPoints => ChannelViewModels.Sum(c => (long)c.DataCount);

    public bool IsLoading
    {
        get => _isLoading;
        set
        {
            _isLoading = value;
            OnPropertyChanged(nameof(IsLoading));
        }
    }

    public bool IsEmpty => ChannelViewModels.Count <= 0;

    public DoubleRange XRange
    {
        get => _xRange;
        set
        {
            _xRange = value;
            OnPropertyChanged(nameof(XRange));
        }
    }
}

+Attached image below is what i want to implement.
++I also attached tried code in .zip .

0 votes
0 answers
8k views

Hello again!
I’m working with new scichart version (5th august). In view XAML file I have this code snippet:

visuals:SciChartSurface Annotations="{Binding AnnotationCollection}"  SeriesSource="{Binding GraphicsCollection}" XAxis="{Binding XAxis, Mode=TwoWay}" YAxes="{Binding YAxisCollection}"  >

When I try to run the application, I get this NullReferenceException:

   в A. .Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
   в System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
   в System.Windows.Data.BindingExpression.Activate(Object item)
   в System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
   в System.Windows.Data.BindingExpression.AttachOverride(DependencyObject target, DependencyProperty dp)
   в System.Windows.Data.BindingExpressionBase.OnAttach(DependencyObject d, DependencyProperty dp)
   в System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   в System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
   в System.Windows.Data.BindingOperations.SetBinding(DependencyObject target, DependencyProperty dp, BindingBase binding)
   в System.Windows.FrameworkElement.SetBinding(DependencyProperty dp, BindingBase binding)
   в Abt.Controls.SciChart.Visuals.Annotations.LineAnnotationWithLabelsBase.VB()
   в Abt.Controls.SciChart.Visuals.Annotations.LineAnnotationWithLabelsBase.TB()
   в Abt.Controls.SciChart.Visuals.Annotations.LineAnnotationWithLabelsBase.OnXAxesCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   в Abt.Controls.SciChart.Visuals.Annotations.AnnotationBase.Abt.Controls.SciChart.Visuals.Annotations.IAnnotation.OnXAxesCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   в Abt.Controls.SciChart.Visuals.Annotations.AnnotationCollection.OnXAxesCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   в Abt.Controls.SciChart.Visuals.SciChartSurface.OnXAxesCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   в System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)

But if I change my xaml file this way:

visuals:SciChartSurface SeriesSource="{Binding GraphicsCollection}" XAxis="{Binding XAxis, Mode=TwoWay}" YAxes="{Binding YAxisCollection}" 
Annotations="{Binding AnnotationCollection}"   >

there won’t be any exceptions. I’ve attached project with exception below.

P.S. in the previuous version it works fine.

  • Egor asked 9 years ago
0 votes
3k views

Hello.
Thanks for previous answer but I can’t check how it work because of new problem. I develop WPF application and try to use MVVM as architecture pattern. In the Model part of my application I used a loop started in the new thread. In that loop I get some data which received to ViewModel and used as chart data. Looks as usual.
But then I tried to set visible range updated object which bound to axis I get exception ‘System.InvalidOperationException: ‘The calling thread cannot access this object because a different thread owns it.’ in my loop. I know it happens in WPF applications and need to use Dispatcher to solve it. But as I know if you try to use MVVM you not needed to use Dispatcher often because WPF-binding in most cases is thread-safe. That happend in my case? How to solve it?
Parts of my code:

XAML

<Window x:Class="HMI.MainWindow"
        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:s="http://schemas.abtsoftware.co.uk/scichart"
        xmlns:localVM="clr-namespace:MyCom.HMI.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <localVM:HMIViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <localVM:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
        <localVM:ProcessStateToColorConverter x:Key="ProcessStateToColorConverter"/>
        <localVM:ProcessStateToStartedConverter x:Key="ProcessStateToStartedConverter"/>
        <localVM:ProcessStateToStoppedConverter x:Key="ProcessStateToStoppedConverter"/>
    </Window.Resources>
    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <StackPanel DockPanel.Dock="Left" Orientation="Vertical" Width="520">
                <Border DockPanel.Dock="Top" Margin="5" Padding="5" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="5">
                    <StackPanel DockPanel.Dock="left" Orientation="Horizontal" Height="40">
                        <Ellipse Margin="5" Height="20" Width="20" HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black" Fill="{Binding ProcessState, Converter={StaticResource ProcessStateToColorConverter}}"/>
                        <Label Content="State" Margin="5" Width="90" HorizontalContentAlignment="Left" VerticalContentAlignment="Center"/>
                    </StackPanel>
                </Border>
                <Border DockPanel.Dock="Top" Margin="5" Padding="5" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="5">
                    <Grid DockPanel.Dock="Left" Height="300">
                        <s:SciChartSurface ChartTitle="Profil" RenderableSeries="{s:SeriesBinding RenderableSeries}">
                            <s:SciChartSurface.XAxis>
                                <s:NumericAxis AxisTitle="Position, m" VisibleRange="{Binding XVisibleRange, Mode=TwoWay}"/>
                            </s:SciChartSurface.XAxis>
                            <s:SciChartSurface.YAxis>
                                <s:NumericAxis AxisTitle="Size, um" VisibleRange="{Binding YVisibleRange, Mode=TwoWay}"/>
                            </s:SciChartSurface.YAxis>
                        </s:SciChartSurface>
                    </Grid>
                </Border>
            </StackPanel>
...

ViewModel

namespace MyCom.HMI.ViewModel
{
    public class HMIViewModel : BindableBase
    {      
        private readonly HMIModel _model = new();

        public HMIViewModel()
        {
            _renderableSeries = new ObservableCollection<IRenderableSeriesViewModel>();

            ((INotifyCollectionChanged)_model.TestControlData).CollectionChanged += (s, e) =>  { TestControlDataChanged(e); };

            InitCharts();
        }

...

        private ObservableCollection<IRenderableSeriesViewModel> _renderableSeries;
        public ObservableCollection<IRenderableSeriesViewModel> RenderableSeries
        {
            get { return _renderableSeries; }
            set
            {
                SetProperty(ref _renderableSeries, value, nameof(RenderableSeries));
            }
        }

        private IRange _xVisibleRange;
        public IRange XVisibleRange
        {
            get => _xVisibleRange;
            set
            {
                if (_xVisibleRange != value)
                {
                    SetProperty(ref _xVisibleRange, value, nameof(XVisibleRange));
                }
            }
        }

        private IRange _yVisibleRange;
        public IRange YVisibleRange
        {
            get => _yVisibleRange;
            set
            {
                if (_yVisibleRange != value)
                {
                    SetProperty(ref _yVisibleRange, value, nameof(YVisibleRange));
                }
            }
        }

        private XyDataSeries<double, double> _lineDataDiameter1;

...

        private void InitCharts()
        { // TODO
            _lineDataDiameter1 = new XyDataSeries<double, double>()
            { 
                SeriesName = "Diameter1"
            };

            RenderableSeries.Add(new LineRenderableSeriesViewModel()
            {
                StrokeThickness = 2,
                Stroke = Colors.SteelBlue,
                DataSeries = _lineDataDiameter1,
                StyleKey = "LineSeriesStyle"
            });
        }

        private void TestControlDataChanged(NotifyCollectionChangedEventArgs args)
        {
            if (args.Action == NotifyCollectionChangedAction.Add && args.NewItems?.Count > 0)
            {
                var testControlActualState = args.NewItems.Cast<TestControlActualState>();

                List<double> xValues = new();
                List<double> yValuesDiameter1 = new();

                foreach (var item in testControlActualState) 
                {
                    if (item.Diameter1 > 0f)
                    {
                        xValues.Add(item.FiberLength);
                        yValuesDiameter1.Add(item.Diameter1);
                    }
                }

                _lineDataDiameter1.Append(xValues, yValuesDiameter1);

                // TODO
                if (xValues.Count > 0)
                {
                    var cuurMaxValueX = xValues.Max();
                    XVisibleRange.Max = cuurMaxValueX;
                    XVisibleRange.Min = cuurMaxValueX - 7000f > 0 ? cuurMaxValueX - 7000f : 0;
                }

                // TODO
                if (yValuesDiameter1.Count > 0)
                {
                    var cuurMaxValueY = yValuesDiameter1.Max();
                    YVisibleRange.Max = cuurMaxValueY + 50;
                    YVisibleRange.Min = 0;
                }
            }
        }

Model

namespace MyCom.HMI.Model
{
    public class HMIModel : BindableBase, IDisposable
    {
        private readonly ObservableCollection<TestControlActualState> _testControlData;
        internal ReadOnlyObservableCollection<TestControlActualState> TestControlData { get; }

        public HMIModel()
        {
            _testControlData = new ObservableCollection<TestControlActualState>();
            TestControlData = new ReadOnlyObservableCollection<TestControlActualState>(_testControlData);
        }

...

        private void StartPollerThread()
        {
            _pollerCancellationToken ??= new CancellationTokenSource();

            if (!_pollerCancellationToken.IsCancellationRequested)
            {
                Task.Factory.StartNew(() => PollerDoWork(_pollerCancellationToken.Token), TaskCreationOptions.LongRunning);
            }
        }

        private void PollerDoWork(CancellationToken cancellationToken)
        {
            try
            {
                Thread.CurrentThread.Priority = ThreadPriority.Lowest;
                IsPollerStarted = true;

                while (!cancellationToken.IsCancellationRequested && (_isKeepConnection || _countOfTrying <= MAX_COUNT_OF_TRYING))
                {
                    try
                    {
                        _testControlData.Add(_emulator.GetTestControlActualState());

                        if (!_isKeepConnection && _countOfTrying > 0)
                        {
                            Thread.Sleep(_pollerTimeout / REASK_COEFICIENT);
                            continue;
                        }
                    }
                    catch
                    {
                        // Thread must be alive!!! ...ALWAYS!!!
                    }
                    Thread.Sleep(_pollerTimeout);
                }
            }
            finally
            {
                IsPollerStarted = false;
                _pollerCancellationToken = null;
            }
        }
0 votes
8k views

I’m trying to set the visible range property of a CategoryDateTimeAxis through MVVM. I’m following the general instructions detailed here for converting between pixel & data coordinates on the axis:

https://www.scichart.com/questions/question/categorydatetimeaxis-in-mvvm#sabai-inline-nav

I have the following code in my viewmodel:

XAxis.OnBeginRenderPass();
var calc = XAxis.GetCurrentCoordinateCalculator();
var coordCalc = calc as ICategoryCoordinateCalculator;

XAxis is a CategoryDateTimeAxis injected from the view. I call OnBeginRenderpass as I saw in another forum post that this will ensure that the CoordinateCalculator is initialized.

calc shows in the debugger as:

  • calc {A.} Abt.Controls.SciChart.Numerics.CoordinateCalculators.ICoordinateCalculator {A.}

The coordCalc variable ends up assigned to NULL, as the ICoordinateCalculator< double > cannot be cast to the interface.

How do I accomplish the above?

Thanks, Asher

  • ashernew asked 8 years ago
  • last active 8 years ago
0 votes
6k views

Hi SciChart team,

I have built a xyscatter chart with DateTime type X-Axis and Double type Y-Axis,
and built boxannotations to mark areas.

May I set the x-Axis value in the tooltip?
Or can I show properties of each item which means every point in the xyscatterseries, and customize the tooltip content style like adding the description of every properties.

  • Wade Yao asked 3 years ago
  • last active 3 years ago
0 votes
11k views

Hello support team.

I have a question about the resampling modes and their behavior.
I have a LineRenderableSeries with the resampling mode.mid. Therefore, depending on the zoom level and available pixels of the display screen, the information of the min and max values are lost. I had the idea to create a second LineRenderableSeries with the Opacity 0.5 and the ResamplingMode.Min Max. Thus I have behind the main line with the resampling mode.mid a “cloud” with the MinMax info. This allows the user to see this information as well. However, I would deactivate this cloud if it is not necessary due to the zoom level and the pixels.
How can I request this from SciChartControl? Or does it make more sense to use a different functionality?
I use the Mvvm classes LineRenderableSeriesViewModel, and XyDataSeries.

Thank you very much!

0 votes
8k views

I am trying to bind from my ViewModel to the DataSeries of a ScatterRenderableSeries3D, but no data is showing.

I am binding in this way:

My ViewModel has a property of type ObservableCollection<XyzDataSeries3D<DateTime, double, int>>. I can populate ChartItems, and see the data in it. The property is being notified of change as expected.

If I populate the DataSeries directly from code behind, it works, but not when being bound.

What am I doing wrong?

0 votes
4k views

Getting an exception when trying to add tooltip template MVVM style to a blox plot. The chart also contains a scatter plot which should not be styled. That works fine, hoverwer, when I move the mouse over a box in the box plot, the exception is thrown.

I want to keep the styling, I just want to write something different than the default text.

The template:

  <DataTemplate DataType="scalarPlot:ToolTipData" x:Key="BoxSeriesTooltipTemplate">
    <TextBlock>
      <Run Text="Max:      " />
      <Run Text="{Binding Maximum}" />
      <LineBreak />
      <Run Text="P90:       " />
      <Run Text="{Binding P90}" />
      <LineBreak />
      <Run Text="Median: " />
      <Run Text="{Binding Median}" />
      <LineBreak />
      <Run Text="P10:       " />
      <Run Text="{Binding P10}" />
      <LineBreak />
      <Run Text="Min:       " />
      <Run Text="{Binding Minimum}" />
      <LineBreak />
    </TextBlock>
  </DataTemplate>

The binding:

      <Style TargetType="s:BaseRenderableSeries" x:Key="BoxSeriesStyle">
        <Setter Property="s:TooltipModifier.TooltipTemplate" Value="{StaticResource BoxSeriesTooltipTemplate}"/>
        <Setter Property="s:TooltipModifier.IncludeSeries" Value="True"/>
      </Style>

The modifier:

<s:SciChartSurface.ChartModifier>
      <s:ModifierGroup>
        <s:TooltipModifier IsEnabled="True" ShowTooltipOn="Always" ReceiveHandledEvents="True" TooltipLabelDataContextSelector="{Binding ToolTipDataContext}"/>
      </s:ModifierGroup>
    </s:SciChartSurface.ChartModifier>

The view model:

    private static IRenderableSeriesViewModel CreateBoxPlotViewModel(BoxPlotDataSeries<int, float> boxPlotDataSeries)
    {
        return new BoxPlotRenderableSeriesViewModel
        {
            DataSeries = boxPlotDataSeries,
            Stroke = Colors.SteelBlue,
            Fill = new LinearGradientBrush(Colors.White, Colors.LightSteelBlue, new System.Windows.Point(0, 0), new System.Windows.Point(0.5, 1)),
            StyleKey = "BoxSeriesStyle"
        };
    }

The data context selector:

    public Func<SeriesInfo, object> ToolTipDataContext
    {
        get
        {
            return seriesInfo =>
                   {
                       return seriesInfo switch
                       {
                           BoxPlotSeriesInfo boxInfo =>
                               new ToolTipData
                               {
                                   Fill = seriesInfo.Fill,
                                   Stroke = seriesInfo.Stroke,
                                   Maximum = (float) boxInfo.MaximumValue,
                                   P90 = (float) boxInfo.UpperQuartileValue,
                                   Median = (float) boxInfo.MedianValue,
                                   P10 = (float) boxInfo.LowerQuartileValue,
                                   Minimum = (float) boxInfo.MinimumValue
                               },
                           _ => seriesInfo
                       };
                   };
        }
    }
  • Tore Munch asked 3 years ago
  • last active 3 years ago
1 vote
7k views

I need the length of the plot area in pixels. I don’t have access to SciChartSurface and it’s XAxis field. I have only ObservableCollection and my NumericAxisViewModel. Is it possible to get the length from them? Or what is the best way to get it in my case?

0 votes
9k views

Hello!

I am trying to programmatically set a range for HeatmapColorPalette and attached HeatmapColorMap to min and max of my data.

Binding HeatmapColorPalette.Maximum to a property in my View Model works well. However, when I add HeatmapColorMap everything breaks, the heat map no longer responds to changes in View Model.

What am I doing wrong?

Here is my View:

<Window x:Class="SciChartHeatMap.MainWindow"
    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:local="clr-namespace:SciChartHeatMap"
    xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
    d:DataContext="{d:DesignInstance Type=local:HeatMapViewModel, IsDesignTimeCreatable=True}"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Grid.Resources>
        <s:GradientStopsToLinearGradientBrushConverter x:Key="ColorsToLinearGradientBrushConverter"/>
    </Grid.Resources>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <s:SciChartSurface Grid.Row="0" Grid.RowSpan="2">
        <s:SciChartSurface.RenderableSeries>
        <s:FastUniformHeatmapRenderableSeries x:Name="HeatMapSeries" DataSeries="{Binding Data}" Opacity="0.9">
            <s:FastUniformHeatmapRenderableSeries.ColorMap>
                <s:HeatmapColorPalette Maximum="{Binding ColorMaximum}">
                    <s:HeatmapColorPalette.GradientStops>
                        <GradientStop Offset="0" Color="DarkBlue"/>
                        <GradientStop Offset="0.2" Color="CornflowerBlue"/>
                        <GradientStop Offset="0.4" Color="DarkGreen"/>
                        <GradientStop Offset="0.6" Color="Chartreuse"/>
                        <GradientStop Offset="0.8" Color="Yellow"/>
                        <GradientStop Offset="1" Color="Red"/>
                    </s:HeatmapColorPalette.GradientStops>
                </s:HeatmapColorPalette>
            </s:FastUniformHeatmapRenderableSeries.ColorMap>
        </s:FastUniformHeatmapRenderableSeries>
        </s:SciChartSurface.RenderableSeries>
        <s:SciChartSurface.XAxis>
            <s:NumericAxis 
                FlipCoordinates="False" 
                ScientificNotation="None" 
                AutoTicks="False"
                MajorDelta="1"
                MinorDelta="0.5"
                AxisAlignment="Top"/>
        </s:SciChartSurface.XAxis>
        <s:SciChartSurface.YAxis>
            <s:NumericAxis 
                FlipCoordinates="True" 
                ScientificNotation="None"
                AxisAlignment="Left"/>
        </s:SciChartSurface.YAxis>
    </s:SciChartSurface>

    <!-- Enabling this will break the program
    <s:HeatmapColorMap
        Grid.Column="1"
        Grid.Row="0"
        Grid.RowSpan="2"
        Margin="5,0,5,0"
        HorizontalAlignment="Right"
        VerticalAlignment="Stretch"
        DataContext="{Binding Source={x:Reference Name=HeatMapSeries}, Mode=OneWay}"
        ColorMap="{Binding ColorMap.GradientStops, Converter={StaticResource ColorsToLinearGradientBrushConverter}}"
        Maximum="{Binding ColorMap.Maximum}"
        Orientation="Vertical">
    </s:HeatmapColorMap>
    -->

    <Label 
        Grid.Row="0" 
        Grid.Column="2" 
        Content="{Binding ColorMaximum}" 
        Width="50" 
        HorizontalContentAlignment="Center"/>
    <Slider 
        Grid.Column="2" 
        Grid.Row="1" 
        Orientation="Vertical" 
        Minimum="0" 
        Maximum="10" 
        HorizontalAlignment="Center"
        Value="{Binding ColorMaximum}"/>
</Grid>

The idea in this small example is for slider to control both HeatmapColorPalette.Maximum and s:HeatmapColorMap.Maximum

The code in my View Model is pretty simple:

private double mColorMax;

public double ColorMaximum
    {
        get => mColorMax;

        set
        {
            mColorMax = value;
            OnPropertyChanged();
        }
    }

My View Model implements INotifyPropertyChanged

I will appreciate any suggestions.

Thank you in advance!

1 vote
12k views

Hello,

I have a scichart and bound to its VM class. Inside this VM there is a Highlights property.

On the MainWindow, I am placing two of this charts with their own VM instance.

The problem is that when the Annotations is bound, it is only drawn on the last chart as shown in the image.

If I manually code in xaml the annotations (no binding) then the annotations are drawn in both charts.

How can I make it work with the binding?

Thanks

  • Miguel Hau asked 10 years ago
  • last active 10 years ago
1 vote
0 answers
994 views

Hello,
I have this

private readonly string CHART_MARKER_TEXT = "Marker";
private readonly string CHART_MARKER_STYLE = "VerticalLineAnnotationStyle"; // defined in Chart.xaml

    AddVerticalLineAnnotation(new AnnotationRequest() { XValue = 3, LabelText = CHART_MARKER_TEXT, AnnotationStyle = CHART_MARKER_STYLE });

private void AddVerticalLineAnnotation(AnnotationRequest request)
{
    Annotations.Add(new VerticalLineAnnotationViewModel
    {
        X1 = request.XValue,
        LabelValue = !string.IsNullOrEmpty(request.LabelText) ? request.LabelText : null,
        VerticalAlignment = VerticalAlignment.Stretch,
        LabelPlacement = LabelPlacement.Left,
        LabelsOrientation = System.Windows.Controls.Orientation.Vertical,
        StyleKey = request.AnnotationStyle,
    });
}

And this

<Style x:Key="VerticalLineAnnotationStyle" TargetType="{x:Type s:VerticalLineAnnotation}">
    <Setter Property="Stroke" Value="Orange" />
    <Setter Property="StrokeThickness" Value="2" />
    <Setter Property="FontSize" Value="12" />
    <Setter Property="FontWeight" Value="Bold" />
</Style>

Why I can’t see Label?

enter image description here
enter image description here

0 votes
11k views

Hi,

Was hoping you could point me in the right direction. I’m trying to create horizontal line annotations on demand using MVVM but have become stuck. I’ve have them working in MVVM when the chart loads but not when a button is clicked although I have achieved this using code behind.

I’ve tried using an observable collection of AnnotationCollection type but am struggling to add the horizontal lines annotations to it as they are of a different type.

Any pointers in the right direction would be much appreciated!

Thanks,
Tim

Example of MVVM

TradeAnnotations = CreateHorizontalAnnotations();

private AnnotationCollection _annotations;

    public AnnotationCollection TradeAnnotations
    {
        get { return _annotations; }
        set
        {
            _annotations = value;
            OnPropertyChanged("TradeAnnotations");
        }
    }

    private static AnnotationCollection CreateHorizontalAnnotations()
    {
        //var annotations = new AnnotationCollection();

        var annotations = new AnnotationCollection();

        Color strokeColor = (Color)ColorConverter.ConvertFromString("#008B45");
        Brush strokeBrush = new SolidColorBrush(strokeColor);

        HorizontalLineAnnotation annotation = new HorizontalLineAnnotation();

        annotation.ShowLabel = true;
        annotation.LabelPlacement = LabelPlacement.Axis;
        annotation.HorizontalAlignment = HorizontalAlignment.Stretch;
        annotation.IsEditable = true;
        annotation.SnapsToDevicePixels = true;
        annotation.Stroke = strokeBrush;

        annotation.X1 = DateTime.Now;
        annotation.Y1 = 129;

        annotations.Add(annotation);

        return annotations;          
    }

Example of code behind

        private void CreateHorizontalAnnotations(object sender, System.Windows.RoutedEventArgs e)
    {
        //var annotations = new AnnotationCollection();

        var annotationCollection = new AnnotationCollection();

        Color strokeColor = (Color)ColorConverter.ConvertFromString("#008B45");
        Brush strokeBrush = new SolidColorBrush(strokeColor);

        HorizontalLineAnnotation annotation = new HorizontalLineAnnotation();

        annotation.ShowLabel = true;
        annotation.LabelPlacement = LabelPlacement.Axis;
        annotation.HorizontalAlignment = HorizontalAlignment.Stretch;
        annotation.IsEditable = true;
        annotation.SnapsToDevicePixels = true;
        annotation.Stroke = strokeBrush;

        annotation.X1 = DateTime.Now;
        annotation.Y1 = 129;

        this.priceChart.Annotations.Add(annotation);
    }
1 vote
14k views

I would like to template items of an AxisCollection assigned to a sciChartSurface in binding of an AxisItemCollectionViewModel. But it looks like I cannot do it as Visual Studio won’t compile my tries.

What i am looking for is something like the EEG 16 channel sample. There the ListBoxItems are styled via a template which is bound to a ViewModelItem. The ListBox itsself is bound to a ViewModelCollection. Depending on how many entries there are entries in the listbox.

So I would like to do something like this:

<SciChartSurface.AxisCollection ItemsSource="{Binding MyAxisCollectionViewModels}" ItemTemplate="{StaticResource AxisItemTemplate}" />

Is this possible? I don’t know how many y-axes i will have. They are configurable by the user.

  • Uwe Hafner asked 9 years ago
  • last active 9 years ago
0 votes
7k views

Is there a way to apply functionalities on signals as in average, slope, etc. ?

Thank you
Anders

0 votes
0 answers
9k views

I try to add data series and have them rendered on a chart surface. The surface and entire chart library is wrapped in an mvvm-based api. The sci chart control and wrapping library are rendered on a document panel. I add new data series via the viewmodel and here is where I have some unexpected behavior:

a) When being on a different document panel, meaning the chart control is NOT visible, and when I add a new data series via view model and then view the document panel that hosts the sci chart control, no chart series are rendered on the chart but I do see the correct legend data (such as chart series name, color, stroke thickness). Please see below screen shot “Capture1.jpg” .

b) When I make the sci chart control visible by viewing the document panel that hosts the sci chart control and then via a button and command add the very same data series via my chart control’s view model the charts are correctly rendered. Please see “Capture2.jpg”.

My question is why is that the case? I basically expose a method in my chart library view model that lets me add data and if I invoke that methods while being on a document panel that does not host the chart control the added data series is not rendered on the chart. But strangely the correct chart legend data are displayed and also the chart control itself is correctly rendered. No problems when the hosting document panel is active and the very same method is invoked.

Basically what I currently observe is that the data series are not rendered at all as long as the chart control is not “in view” or the hosting document panel is not selected. I am sure programmatically all references and bindings are correct.

I have spend many hours debugging this issue and do not seem to find an answer. Any pointers?

Thanks a lot,
Matt

Edit:

Here is how I bind the content control to the view model of my sci chart charting library (user control)

<ContentControl Grid.Row="1" Content="{Binding ChartControl, Mode=OneWay}" />

…and the view model is instantiated in the hosting view model constructor:

public MainWindowViewModel()
    {
       ChartControl = new SciChartControlViewModel();

        ExitApplicationCommand = new RelayCommand(OnExitApplicationCommand);
        LoadDataSeriesFromFilesCommand = new RelayCommand(OnLoadDataSeriesFromFilesCommand);
        RefreshDataSeriesFromFilesCommand = new RelayCommand(OnRefreshDataSeriesFromFilesCommand);


        Test();

    }

…Test() performs the following action:

private void Test()
    {
        var quotes = new List<Quote>();
        List<DateTime> timeStamps = new List<DateTime>();
        List<double> values = new List<double>();
        List<SciChartAnnotation> annotations = new List<SciChartAnnotation>();
        Random rand = new Random((int)DateTime.Now.Ticks);
        DateTime currentDt = DateTime.Now;
        double currentValue = 0;

        for (int index = 0; index <= 50000; index++)
        {
            var randomValue = rand.NextDouble();
            currentDt = currentDt + TimeSpan.FromSeconds(randomValue);
            currentValue = currentValue + randomValue - 0.5;

            if (index % 1000 == 0)
            {
                var buySell = rand.NextDouble() > 0.5 ? SciChartAnnotationDirection.Buy : SciChartAnnotationDirection.Sell;
                annotations.Add(new SciChartAnnotation(buySell, currentDt, currentValue, "Index:" + index));
            }

            timeStamps.Add(currentDt);
            values.Add(currentValue);

            quotes.Add(new Quote(){DataProviderId = "Provider1", SymbolId = "Symbol1", QuoteType = QuoteType.BidAsk, CompressionType = TimeCompressionType.NoCompression, CompressionUnits = 0, TimeStamp = currentDt, Bid = currentValue, Ask= currentValue + 0.05, });

        }

        ChartControl.AddDataSet("Pane1", "0.00000", quotes, annotations);
        //ChartControl.AddDataSet("MattSeries", ChartType.Scatter, 1, "0.00000", timeStamps, values);

    }

…it basically tries to render chart series and annotations.

Strangely, as mentioned before, the series legends render correctly and the annotations also all render correctly but the chart series do not! Could this be a bug? Please refer to the image “Capture3” for a screenshot.

  • bbmat asked 9 years ago
  • last active 9 years ago
1 vote
13k views

I am trying out SciChart ( and WPF ) for a large dataset and till so far very pleased with the results. I have followed the example as described here http://support.scichart.com/index.php?/Knowledgebase/Article/View/17258/0/creating-a-custom-scichartoverview-with-many-series-using-the-scrollbar-api and can successfully view my bound data and everything is perfect for the first instance.

However, when I assign this usercontrol to different tabs they still somehow share data about the viewstate ( the overview window does not resize, and the slider thing in front of it stays at the same values. My guess is that it has to do with the messages in ActualSizePropertyProxy , but since I am new to SciChart and WPF I was hoping that maybe someone here knows what it is.

Thanks.

  • Michel Moe asked 9 years ago
  • last active 4 years ago
0 votes
8k views

Hi,

I have several chart panes that share a mouse group and a shared visual range (I inject the shared visual range of type IRange in the constructor of the pane view model). I then set the XAxis visual range to the shared visual range inside each pane view model. However, when I use either of the below approaches outside of the pane view model to adjust the min and max of shared visual range, the Xaxis.VisualRange of each pane does not reflect that change.

Approach A: _sharedVisualRange.Min = ….; _sharedVisualRange.Max = …
Approach B: _sharedVisualRange.SetMinMax(….)

Neither approach actually impacts the XAxis.VisualRange.Min/Max.

Initially when I created the XAxis in code I set its VisualRange equal to the shared visual range that was injected via constructor, like :

XAxis = new CategoryDateTimeAxis()
{
……
……
VisualRange = _sharedVisualRange,
…..
};

Please note that all the above refers to code in the view model. I bind the XAxis in the pane view model to the XAxis of the surface in xaml.

My entire synchronization heavily relies on the assumption of this working, but it does not.

  • bbmat asked 6 years ago
  • last active 6 years ago
1 vote
9k views

Hello, SciChart Team!
i have an issue using mouse drag event ( RubberBandXyZoomModifier, ZoomPanMidifier). the message says “NullReferenceException in SciChart.Charting.dll ” or “Thread.cs not found” from time to time.
after some experiments i figured out that the app starts to crush after i change XAxis type .
i have a simple mvvm user control used to display both arrays of double and datebound data, XAxes of SciChart Surfase is bound to an observable collection of IAxis elements. if i need to change chart type i clear this collection and create an axis of desired type (DateTimeAxisViewModel or NumericAxisViewModel). after that the series can be added, but zooming causes crash with nearly to no info.

i attached a solution, which lacks only scichart dlls in order to run (hopefully), Window_Loaded method has a commented line which changes chart type and makes app crush on zooming, would be nice if you checked it out.
Thanks in advance!
Alexander

1 vote
3k views

Hello,
I’ve got Annotations ViewModels collection (BoxAnnotationViewModel, VerticalLineAnnotationViewModel, LineAnnotationViewModel) bound by AnnotationsBinding. Every Annotation ViewModel has properties set to:

CoordinateMode = AnnotationCoordinateMode.Absolute
IsEditable = true
DragDirections = XyDirection.XYDirection
ResizeDirections = XyDirection.XYDirection

My goal is to move and resize every annotation on SciChart surface only by integer value. Is there any way to achieve this?

Best regards,
Anna

1 vote
6k views

Hello,
I’m currently rewriting a program in .net7 WPF using MVVM as much as possible.

In my MainViewModel:

I read data from a CSV file and transforming it into an ObservableCollection of LineRenderableSeriesViewModel (stored in the « RenderableSeriesViewModels » variable) . Additionally, the Y axes are transformed into ObservableCollection of IAxisViewModel (within the « Yaxes » variable).
Each series corresponds to a LineRenderableSeriesViewModel and each Y axis is represented as a NumericAxisViewModel. The X-axis is a DateTime common to all series and is declared only in XAML.

Within my view’s XAML:

I declare RenderableSeries=”{s:SeriesBinding RenderableSeriesViewModels}” and YAxes=”{s:AxesBinding YAxes}. I’ve defined a legend template to add several elements:
– DataContext=”{Binding RenderableSeries}”
– A checkbox to toggle serie visibility (IsVisible binding).
– A checkbox to toggle Y-axis visibility for the serie (YAxis.Visibility binding).
– A color picker to change the color of a serie, bound to “Stroke”, “YAxis.TickTextBrush”, and “YAxis.BorderBrush”
– A slider for adjusting serie thickness (StrokeThickness binding).

Results:

Each element acts on the graph as expected: RenderableSeries updates and the graph refreshes correctly.

In the MainViewModel, RenderableSeriesViewModels and YAxes are not updated for all elements:
– “IsVisible” and “StrokeThickness” for the concerned series are instantly modified in RenderableSeriesViewModels but “Stroke” is not.
– “YAxes” is not updated.

The code for the LegendTemplate and a screenshot of the resulting legend are in the attachements.

Could you please help me to understand what I do wrong?

1 vote
11k views

Hi,

I am having a problem with two SciChartSurface’s sharing the same ViewModel instance. I am using the Master-Detail View pattern to provide a list of charts (Collection of SciChart surfaces) with continuously updating data from a device) within a Listbox container on the left-hand side. On the right-hand side I provide the current selected chart with extended size and some extra controls.

The visual appearance of the SciChartSurface (shared across both sides) is defined via data template

<Window.Resources>
    <local:WorkspaceViewModel x:Key="WorkspaceViewModel" />
    <DataTemplate x:Key="ChartDataTemplate">
        <Border MinHeight="200">
            <visuals:SciChartSurface DebugWhyDoesntSciChartRender="True"
                                     visuals:ThemeManager.Theme="BrightSpark"
                                     SeriesSource="{Binding ., Mode=TwoWay}">
                <visuals:SciChartSurface.XAxis>
                    <visuals:NumericAxis VisibleRange="0.0, 10.0"
                                         AutoRange="Always" />
                </visuals:SciChartSurface.XAxis>

                <visuals:SciChartSurface.YAxis>
                    <visuals:NumericAxis VisibleRange="-1.0, 1.0"
                                         AxisAlignment="Left"
                                         AutoRange="Always" />
                </visuals:SciChartSurface.YAxis>
                <visuals:SciChartSurface.ChartModifier>
                    <visuals:SeriesValueModifier ReceiveHandledEvents="True"></visuals:SeriesValueModifier>
                </visuals:SciChartSurface.ChartModifier>
            </visuals:SciChartSurface>
        </Border>
    </DataTemplate>
</Window.Resources>

and is used within the ListBox and ContentControl in the following way

<Grid DataContext="{StaticResource WorkspaceViewModel}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200*"
                          MinWidth="225"
                          MaxWidth="700" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="375*" />
    </Grid.ColumnDefinitions>

    <GroupBox Grid.Column="0">
        <ListBox x:Name="ListBox"
            SelectedItem="{Binding SelectedChart}"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch"
                 ItemsSource="{Binding Charts}"
                 HorizontalContentAlignment="Stretch"
                 ItemTemplate="{StaticResource ChartDataTemplate}" />
    </GroupBox>
    <GridSplitter Grid.Column="1"
                  Width="5"
                  HorizontalAlignment="Right"
                  VerticalAlignment="Stretch"
                  ResizeBehavior="PreviousAndNext" />
    <GroupBox Grid.Column="2">
        <ContentControl x:Name="ContentControl"
            Content="{Binding SelectedChart}"
                        ContentTemplate="{StaticResource ChartDataTemplate}" />
    </GroupBox>
</Grid>

The ViewModel (WorkspaceViewModel) contains two properties:

ObservableCollection<ObservableCollection<IChartSeriesViewModel>> Charts
public ObservableCollection<IChartSeriesViewModel> SelectedChart

So far, so good. Once populated with live chart data, the ListBox displays all charts with live updating of the DataSeries. The issue I encounter is that once a chart in the ListBox is selected, the Detail View gets updated and continues displaying live data updates, but the ListBox entry stops updating. Obviously the sharing of the same instance of IChartSeriesViewModel in two different SciChartSurface views (via the ViewModel property SelectedChart) is causing trouble.

What am I missing here? I am currently using SciChart 3.0.

Many thanks,

Silvio

  • swiedric asked 10 years ago
  • last active 10 years ago
0 votes
8k views

There doesn’t seem to be a corresponding IRenderableSeries3DViewModel object like there is in the 2D charts. What am i suppose to bind to the RenderableSeries property of the SciChart3DSurface? If I bind to a

ObservableCollection<IRenderableSeriesViewModel>

object, then I don’t see a corresponding SurfaceMeshRenderableSeries3DViewModel object similar to LineRenderableSeriesViewModel for 2D?

A simple example of series binding using 3D charts would be great!

  • Andy None asked 7 years ago
  • last active 5 years ago
0 votes
9k views

Hi,

I’ve been finding lots of examples of creating Custom Chart Modifiers however they are not using a SciChartGroup using a DataTemplate and not in a MVVM scenario.

I know MVVM is the preferred structure for WPF solutions, however it does introduces some complexities as well as using DataTemplates of a SciChartGroup, therefore, would someone please be so kind as to point me in the right direction for an example or two so that I can see how this all could work together?

I’m looking at Custom Chart Modifiers by use of a CustomModifier class. As this will give me the most flexibility in terms of what I would like to do in the future and I would also like to be able to switch between modifiers, such as Panning, Zooming and drawing annotations onto the chart.

Thanks everyone!

David

P.S. Andrew, if this requires a developer on your side to hash this out for an hour or so, let me know and I’ll be more than happy to pay for it.

  • David T asked 9 years ago
  • last active 9 years ago
1 vote
12k views

I’m implementing a toggle between joined and separated axes for my series and I’ve encountered a problem with my SeriesValueModifiers. The modifier seems to be connected to “DefaultAxisId”, when I have my series linked to an axis with that ID the values show up as expected. However, when I separate my series to individual axes the modifiers no longer appears.

Is it possible to collect and show all my SeriesValueModifiers on one axis (keeping the others invisible)? Or perhaps show modifiers on all the axes and stack them on top of each other, keeping labels invisible.

This is the code I’ve got right now:

Adding an axis in my constructor, this one will be used when all the series are using the same axis.

ChartYAxes.Add(new NumericAxis()
{
    Visibility = Visibility.Visible,
    AutoRange = AutoRange.Always,
});

Then I add a new axis for each series.

ChartYAxes.Add(new NumericAxis
{
    Id = tagName,
    Visibility = Visibility.Collapsed,
    AutoRange = AutoRange.Always
});

var renderableSeries = new FastLineRenderableSeries
{
    YAxisId = IsIsolatedCharts ? tagName : "DefaultAxisId"
};

Toggling between these works great, but I need the value labels for this to be useful in any way.

EDIT: In case it’s relevant, here’s the code for toggling.

private void SplitAxes()
{
    var count = Series.Count;
    for (int i = 0; i < count; i++)
    {
        var series = Series[i];
        var name = series.DataSeries.SeriesName;
        //The axes are also added to a dictionary for easy access.
        _axisDictionary[name].GrowBy = new DoubleRange(count - i - 1, i);
        series.RenderSeries.YAxisId = name;
    }
}

private void JoinAxes()
{
    foreach (var series in Series)
        series.RenderSeries.YAxisId = "DefaultAxisId";
}
1 vote
5k views

Hello

In Tutorial 06b – Realtime Updates, I want change the <s:SciChartSurface.XAxis> from <s:NumericAxis/> to <s:DateTimeAxis/> . I have tried a lot, but it still doesn’t work.

Could you please help me to do this work.

Thank you very much.

  • Zhi Zhang asked 7 months ago
  • last active 7 months ago
0 votes
10k views

Hello,

I’m trying to display a vertical line annotation on a chart using MVVM.

In order to make it work I’ve (All the INotifyPropertyChanged are managed via the BaseViewModel)

public class GraphSurfaceBaseViewModel : BaseViewModel
{
    /// <summary>
    /// A list of annotations
    /// </summary>
    public ObservableCollection<IAnnotationViewModel> Annotations { get; private set; }

 ...
}

I create annotation that way

Graph.Annotations.Add(new VerticalLineAnnotationViewModel()
            {
                X1 = TimeOfComment,
                ShowLabel = true,
                StrokeThickness = 2,
                XAxisId = "Xaxis",
                YAxisId = "Yaxis1",
                AnnotationLabels = new ObservableCollection<AnnotationLabel>() { new AnnotationLabel() {Text = "mon test", LabelPlacement = LabelPlacement.TopRight } }

            });

And the binding to the scichartsurface is :

<s:SciChartSurface   
...         
Annotations="{s:AnnotationsBinding Annotations}"            
</s:SciChartSurface>

I’ve double check that my x axis and y axis have the same ID as the annotation.
The problem is I want to display several annotation labels but they are not appearing. I suspect a problem via the AnnotationsBinding which is not taking the AnnotationLabels from the VerticalLineAnnotationViewModel.

What I got :
enter image description here

What I want (paint skill here):
enter image description here

For the what I want, I can draw a simple vertical bar by settings showLabel = false but I suppose that all the label I previously added to the
AnnotationLabels will not be shown, that’s why I let it.

Thank you for any help.

Renaud

0 votes
6k views

Hi,

I am developing an MVVM WPF application and need to access the SelectedPointMarkers property of DataPointSelectionModifier from the ViewModel.

From looking at the DataPointSelectionModifier documentation (https://www.scichart.com/documentation/win/current/webframe.html#DataPoint%20Selection.html) I can see how you can get the X and Y coordinate values of a selected point in a view, by binding the PointMarkersSelectionModifier to a listbox.

However this doesn’t really help me, I need to get the coordinates of the SelectedPointMarker into a property inside the ViewModel that can be accessed, rather than just binding to a listbox in the view itself.

I’ve also looked at this similar post: (https://www.scichart.com/questions/wpf/i-want-to-bind-selectedpointmarkers-of-datapointselectionmodifier), but I had no luck getting Kenishis solution to work in my case.

How can i do this?

Thanks.

1 vote
9k views

Requirements:

  • Main graph updates based on the data from the selected Item.
  • The data and styling is independent and the style is dynamic global style for all Items.
  • The data for the graphing that is Data Series is binded to DataSet which is of type XYDataSeries<DateTime, double>.
  • DataSeries data is obtained from the datacontext which implements INotifyPropertyChanged

Problem:

  • The databinding is not dynamic and the data series is not updated when the selection changes.
  • The initial data selection is reflected but any subsequent data changes are not reflected on the sci chart surface.
  • This behavior was only for the Dataseries binding and it was verified using a textbox which binds to the count of the DataSet and this updates as the selection changes but not the dataseries.

Please suggest a work around or an alternative solution so that I can predefine axes and series but swap out the data based on the selected Item. Please see the attached xaml code below.

        <Grid>
        <Grid DockPanel.Dock="Top">
            <chart:SciChartSurface x:Name="mainView"
                                   OnRenderException="MainView_OnRenderException"
                                   Loaded="MainView_Loaded">
                <chart:SciChartSurface.YAxes>
                    <chart:NumericAxis x:Name="AxisOne"
                                       Id="Id1"
                                       AxisAlignment="Left"/>

                    <chart:NumericAxis x:Name="AxisTwo"
                                       Id="Id2"
                                       AxisAlignment="Left"/>

                </chart:SciChartSurface.YAxes>
                <chart:SciChartSurface.XAxis>
                    <chart:DateTimeAxis x:Name="DateTimeAxis"/>
                </chart:SciChartSurface.XAxis>
                <chart:SciChartSurface.RenderableSeries>
                    <chart:FastLineRenderableSeries x:Name="DataSet1FS"
                                                    DataSeries="{Binding DataSet1}"
                                                    YAxisId="Id1"
                                                    Stroke="Yellow"/>
                </chart:SciChartSurface.RenderableSeries>
            </chart:SciChartSurface>
        </Grid>
        <TextBlock Text="{Binding Path=DataSet1.Count}"
                            Margin="0 -20 0 0"
                            HorizontalAlignment="Right"
                            VerticalAlignment="Top"
                            Height="20"
                            Width="200"
                            Background="White"
                            Foreground="Black"/>
    </Grid>
0 votes
18k views

I am directly editing my XyDataSeries on a chart by using my mouse. As the mouse moves I edit either the x or y value of a point using the methods

    public void SetPointYValueAt(IDataSeries series, int index, double newValue)
    {
        series.YValues[index] = newValue;
        series.InvalidateParentSurface(RangeMode.None);
    }

    public void SetPointXValueAt(IDataSeries series, int index, double newValue, double xMin, double xMax)
    {
        var xValue = newValue;

        // limit x values to keep them sorted
        if (xValue < xMin) xValue = xMin;
        if (xValue > xMax) xValue = xMax;
        series.XValues[index] = xValue;

        series.InvalidateParentSurface(RangeMode.None);
    }

With this code I am not getting an update at my ViewModel:

    public IDataSeries<double, double> MyDataSeries
    {
        get { return _myDataSeries; }
        set
        {
            _myDataSeries = value;
            OnPropertyChanged("MyDataSeries");
        }
    }

Here is my XAML:

            <sciChartExtensions:StepLineRenderableSeries x:Name="HResitivitySeries" IsDigitalLine="True" DataSeries="{Binding MyDataSeries, Mode=TwoWay}">

Where StepLineRenderableSeries is derived from FastLineRenderableSeries with IsDigitalLine = true and the HitTest method overridden.

How can I get MyDataSeries to update?

0 votes
8k views

Hi,

CompositeAnnotation works perfectly and easy to use, but I need it in MVVM. CompositeAnnotationViewModel looks the same, but it is not visible. This is my code:

AnnotationViewModels.Add(new CompositeAnnotationViewModel()
{
    Annotations = new ObservableCollection<IAnnotationViewModel>()
    {
        new VerticalLineAnnotationViewModel
        {
            VerticalAlignment = VerticalAlignment.Stretch,
            Stroke = Colors.Blue,
            StrokeThickness = 2,
            IsEditable = true,
            StrokeDashArray = new DoubleCollection() { 2, 2 },
            CoordinateMode = AnnotationCoordinateMode.Relative,
            X1 = 0
        },
        new VerticalLineAnnotationViewModel
        {
            VerticalAlignment = VerticalAlignment.Stretch,
            Stroke = Colors.Blue,
            StrokeThickness = 2,
            IsEditable = true,
            StrokeDashArray = new DoubleCollection() { 2, 2 },
            CoordinateMode = AnnotationCoordinateMode.Relative,
            X1 = 1
        }
    },
    IsEditable = true,
    X1 = 3,
    X2 = 5
});

What is my mistake?

0 votes
3k views

Hi sir,

We would like to build a real time updated stackedcolumn chart in mvvm mode.
Is that possible? (x-axis on the left side)(y-axis on the bottom side which can keep update with only 10mins range)

I wonder can I use the StackedColumnRenderableSeriesForMvvm?
I found out this control but have no idea how to use it…

  • Wade Yao asked 3 years ago
  • last active 3 years ago
0 votes
2k views

Hello,
I am trying to add a BoxAnnotation with MVVM pattern where the X-Axis is a DateTime axis. The annotation can be dragged into the X-direction. I need to know the DateTime of each position while dragging and also the final position(DateTime) of the BoxAnnotation when the drag Ended. I am listening to the DragDelta and DragEnded events in ViewModel. But here I couldn’t able to get the DateTime from X1 and X2 of that annotation model. I am sharing some snippets of my code. Can you please let me know how I can achieve this?

In xaml:

<Style x:Key="_boxAnnotationStyle" BasedOn="{StaticResource AnnotationBaseStyle}" TargetType="scichart:BoxAnnotation">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="scichart:BoxAnnotation">
                    <Border x:Name="PART_BoxAnnotationRoot"
              Margin="{TemplateBinding Margin}"
              Background="{TemplateBinding Background}"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}"
              CornerRadius="{TemplateBinding CornerRadius}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>
<scichart:SciChartSurface x:Name="GraphSurface"
                 Annotations="{scichart:AnnotationsBinding ItsAnnotations}">

                <scichart:SciChartSurface.XAxis>
                    <scichart:DateTimeAxis x:Name="GraphXAxis"
                                           VisibleRange="{Binding ItsTimeVisibleRange, Mode=TwoWay}" />
                </scichart:SciChartSurface.XAxis>

                <scichart:SciChartSurface.YAxes>
                    <scichart:NumericAxis x:Name="GraphYAxis"
                                          VisibleRange="0, 10" />

                </scichart:SciChartSurface.YAxes>
 </scichart:SciChartSurface>

In ViewModel.cs

{
    private DateRange _timeVisibleRange;
    private ObservableCollection<IAnnotationViewModel> _annotations;
    private IAnnotationViewModel _boxAnnotation;
    public ObservableCollection<IAnnotationViewModel> ItsAnnotations
    {
        get
        {
            return _annotations;
        }
    }
    public DateRange ItsTimeVisibleRange
    {
        get { return _timeVisibleRange; }
        set
        {
            if (_timeVisibleRange == value) return;
            _timeVisibleRange = value;
            RaisePropertyChanged(() => ItsTimeVisibleRange);
        }
    }
    .
    .
    .
    _boxAnnotation = new BoxAnnotationViewModel()
        {
            IsEditable = true,
            DragDirections = SciChart.Charting.XyDirection.XDirection,
            X1 = DateTime.UtcNow.AddSeconds(300),
            X2 = DateTime.UtcNow,
            Y1 = 0,
            Y2 = 8,
            StyleKey = "_boxAnnotationStyle"
        };

     _annotations = new ObservableCollection<IAnnotationViewModel>() { };
     _annotations.Add(_boxAnnotation );

     _captureTimeRangeSelectorAnnotation.DragDelta += OnDrag;
     _captureTimeRangeSelectorAnnotation.DragEnded += DragEnded;
       .
       .
       .
    private void DragEnded(object sender, EventArgs e)
    {
         var boxAnnotationModel = sender as BoxAnnotationViewModel;
          // Need to know the DateTime value of X1 and X2
    }
    private void OnDrag(object sender, AnnotationDragDeltaEventArgs e)
    {
         var boxAnnotationModel = sender as BoxAnnotationViewModel;
         // Need to know the DateTime value of X1 and X2
    }
    .....
    .....
}
1 vote
5k views

Previously I used AnnotationCreationModifier and my custom annotations were added by one left button mouse click on the chart surface (the annotation was added to the collection and the event handler “AnnotationCreated” fired). Now I’m trying to switch to using the mvvm pattern and I have problems adding my custom annotations using AnnotationCreationModifierMVVM.

Now it works like this:
1) I click (mouse left button) on the chart surface to add an annotation and it is added to the collection and displayed.
2) I click on the chart surface again, and only after that the event handler “AnnotationCreated” is called.

If I carry out some external manipulations with the added annotation between first and second click (for example, moving to the given coordinates by the button click), annotation moved, but when I hover the mouse over the chart surface, it returns to it’s original position. And this behavior will be until I click again on the chart surface so that the event handler “AnnotationCreated” is called.

The built-in annotations work fine though (for examle, VerticalLineAnnotationViewModel or HorizontalLineAnnotationViewModel are successfully added to the collection and call the event handler “AnnotationCreated” by one click on chart surface).

Is it possible to somehow fix this behavior of the custom annotation so that it is added to the collection and triggers an event “AnnotationCreated” for one click on the chart surface, as was the case with AnnotationCreationModifier? I am attaching an example code:

MainWindow.xaml

<Window x:Class="WpfAppMvvm.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
    xmlns:ext="http://schemas.abtsoftware.co.uk/scichart/exampleExternals"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <s:SciChartSurface Annotations="{s:AnnotationsBinding Annotations}">
        <s:SciChartSurface.XAxis>
            <s:NumericAxis AxisTitle="X"/>
        </s:SciChartSurface.XAxis>
        <s:SciChartSurface.YAxis>
            <s:NumericAxis AxisAlignment="Left" AxisTitle="Y"/>
        </s:SciChartSurface.YAxis>
        <s:SciChartSurface.ChartModifier>
            <s:ModifierGroup>
                <s:AnnotationCreationModifierMVVM IsEnabled="True" AnnotationViewModelsCollection="{Binding Annotations}" AnnotationViewModelType="{Binding AnnotationType}">
                    <i:Interaction.Behaviors>
                        <ext:EventToCommandBehavior Command="{Binding AnnotationCreatedCommand}" Event="AnnotationCreated" PassArguments="True"/>
                    </i:Interaction.Behaviors>
                </s:AnnotationCreationModifierMVVM>
            </s:ModifierGroup>
        </s:SciChartSurface.ChartModifier>
    </s:SciChartSurface>
</Grid>

MainWindow.xaml.cs

using System.Windows;
namespace WpfAppMvvm
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
    }
}

MainWindowViewModel.cs

using SciChart.Charting.ChartModifiers;
using SciChart.Charting.Common.Helpers;
using SciChart.Charting.Model.ChartSeries;
using SciChart.Examples.ExternalDependencies.Common;
using System;
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfAppMvvm
{
    internal class MainWindowViewModel:BaseViewModel
    {
        public ObservableCollection<IAnnotationViewModel> Annotations { get; private set; }
        public Type AnnotationType { get; private set; }
        public ActionCommand<AnnotationCreationMVVMArgs> AnnotationCreatedCommand { get; private set; }

        public MainWindowViewModel()
        {
            Annotations = new ObservableCollection<IAnnotationViewModel>();
            AnnotationType = typeof(MyCustomAnnotationViewModel);
            AnnotationCreatedCommand = new ActionCommand<AnnotationCreationMVVMArgs>(ExecCmd, e => true);
        }
        private void ExecCmd(AnnotationCreationMVVMArgs e)
        {
            MessageBox.Show("OnAnnotationCreated executed");
        }
    }
}

MyCustomAnnotation.xaml

<s:CustomAnnotationForMvvm x:Class="WpfAppMvvm.MyCustomAnnotation"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
         d:DesignHeight="450" d:DesignWidth="800">
<Grid>
    <Ellipse
        Width="20"
        Height="20"
        Fill="Transparent"
        Stroke="Red"
        StrokeThickness="3"
    />
</Grid>

MyCustomAnnotation.xaml.cs

using SciChart.Charting.Visuals.Annotations;

namespace WpfAppMvvm
{
    public partial class MyCustomAnnotation : CustomAnnotationForMvvm
    {
        public MyCustomAnnotation()
        {
            InitializeComponent();
        }
    }
}

MyCustomAnnotationViewModel.cs

using SciChart.Charting.Model.ChartSeries;
using System;

namespace WpfAppMvvm
{
    public class MyCustomAnnotationViewModel:CustomAnnotationViewModel
    {
    public override Type ViewType => typeof(MyCustomAnnotation);
    }
}
0 votes
7k views

Hi,

Could you provide some Mvvm examples that include:

1) Mvvm bubble chart where the Fill color is defined on the series view model
2) custom tooltips per point where the tooltip string is defined on the point view model

I have both of these kind of working using a workaround based on the obsolete SciChartSurface.SeriesSource property, but now I’m trying to migrate to SciChartSurface.RenderableSeries and the proper Mvvm API and I cannot find all the elements I need.

Cheers
Felix

  • F W asked 8 years ago
  • last active 8 years ago
1 vote
8k views

Hi all,

I am trying to save a copy of my chart in form of a “Png” image. However I keep getting the following exception:

“Element already has a logical parent. It must be detached from the old parent before it is attached to a new one”

I was wondering if anyone could help me passing through this.

Here is what I do:

I have a main chart surface in my program of which properties are bound to my ViewModel. For instance, as can be seen from the snippet below, my SciChartSurface’s YAxes is bound to an AxisCollection that resides in my ViewModel. Same thing is done for the RenderableSeries, Annotations, ChartModifierGroup, ChartVisibility and the XAxis properties of my Chart Surface:

<sci:SciChartSurface Grid.Row="1" Grid.Column="0"  
                         RenderableSeries="{Binding SciChartSeriesViewModels}"    
                         Padding="0,8,0,2"                                         
                         sci:ThemeManager.Theme="BrightSpark"                                       
                         YAxes="{Binding SciChartYAxesCollection, Mode=TwoWay}"                                         
                         AutoRangeOnStartup="True"                                       
                         Annotations="{Binding ChartAnnotations}"                                     
                         x:Name="ApplicationSciChart"                                       
                         ChartModifier ="{Binding ChartModifierGroup}"
                         BorderBrush="LightSlateGray"
                         BorderThickness="1"
                         Visibility="{Binding ChartVisibility}"
                         XAxis="{Binding SciChartXAxis}">
    </sci:SciChartSurface>

Now, In order to save a copy of my chart into a “Png” file, I created a new SciChartsurface in my Viewmodel. This newly created chart is desired to be rendered in the memory so I can save it as an Image (Very similar to what is instructed in: Screenshots, Printing and Export to XPS Traingin module. Somewhere in my ViewModel, after I generated all the required data for creating my chart, I call a function to form a new SciChart (rendered in memory) and perform the saving action:

private void SaveChart()
    {
        SciChartSurface AppSciChart = new SciChartSurface()
        {
            RenderableSeries = SciChartSeriesViewModels,
            XAxis = new TimeSpanAxis(),
            YAxes = SciChartYAxesCollection,
            ChartTitle = "Rendered in memory",
            Annotations = ChartAnnotations
        };

        var parent = AppSciChart.Parent;
        AppSciChart.Width = 1920;
        AppSciChart.Height = 1080;

         ThemeManager.SetTheme(AppSciChart, "BrightSpark");
         AppSciChart.ExportToFile("C:\\Chart.png",SciChart.Core.ExportType.Png, false);

    }

The RenderableSeries, YAxis and Annotations of the Chart Surface in the above code (AppSciChart) are the same as the ones I used for my main chart in my XAML code (First Snippet above).

My main chart surface in my application shows up fine, and performs what it is supposed to, but as soon as the SaveChart() is called, the program stops with an Unhandled Exception: System.InvalidOperationException: ‘Element already has a logical parent. It must be detached from the old parent before it is attached to a new one.’

I was wondering if anybody could let me know what I am possibly missing here!

Many thanks!

0 votes
7k views

Hi,
I’m experimenting with the LegendModifier and want to control which RenderableSeries are shown via the “LegendItemTemplate” approach. The idea is to add a specific tagging class to the RenderableSeries.DataSeries.Tag and use the content inside the LegendItemTemplate which I define in the Window.Resouces.

The tagging Class:

public class DataSeriesTag
{
    public string LegendText { get; set; }
    public bool ShowLegend { get; set; }
}

The LegendItemTemplate:
<Window.Resources>


<Grid.ColumnDefinitions>

</Grid.ColumnDefinitions>

            <!--<CheckBox Width="16" Margin="5,0,0,0"
                HorizontalAlignment="Left"
                VerticalAlignment="Center"
                IsChecked="{Binding RenderableSeries.IsVisible, Mode=TwoWay}"
                Visibility="{Binding RenderableSeries.DataSeries.Tag.ShowLegend, Converter={dxmvvm:BooleanToVisibilityConverter}}" />-->

            <s:PointMarker Grid.Column="1" Margin="5,0,0,0" Width="40" Height="10" VerticalAlignment="Center" HorizontalAlignment="Center"
              DataContext="{Binding RenderableSeries}"
              DeferredContent="{Binding LegendMarkerTemplate}"
              Visibility="{Binding ShowSeriesMarkers, RelativeSource={RelativeSource AncestorType=s:SciChartLegend}, Converter={dxmvvm:BooleanToVisibilityConverter}}" />

            <TextBlock Margin="5,0,5,0"
     Grid.Column="2"
     HorizontalAlignment="Left"
     Text="{Binding RenderableSeries.DataSeries.Tag.LegendText}" />

        </Grid>
    </DataTemplate>
</Window.Resources>

As long as I declare the SciChartSurface.ChartModifier in XAML, it works perfect.
The proplem raises when I bind the ModifierGroup to a ViewModel Property and try to build the LegendModifier there. How can I assign the LegendItemTemplate in the ViewModel?:

legendModifier = new LegendModifier(){
            ShowLegend = true,
            ShowVisibilityCheckboxes = false,
            LegendItemTemplate = ??????
        };
        TheModifiers.ChildModifiers.Add(legendModifier);

Kind regards
Martin

1 vote
13k views

I saw in tips and tricks for performance the use of

scichartsurface.suspendupdate

before something is added to the dataseries. But usually I don’t have access in ViewModel to surface. How can I suspendupdate in the ViewModel when updating the series?

Is dataseries.SuspendUpdate used for this?

  • Uwe Hafner asked 9 years ago
  • last active 9 years ago
Showing 1 - 50 of 79 results

Try SciChart Today

Start a trial and discover why we are the choice
of demanding developers worldwide

Start TrialCase Studies