MindFusion.WinForms Pack, 2016.R1

MindFusion Pack for WinForms, 2016.R1 has been released. Here is an overview of the new features. You can find details about each new feature here.

Visual Studio 2015 support
MindFusion Pack for WinForms now includes support for Visual Studio 2015. The installer can create VS2015 toolbox palette for the components.

Barcodes
The new BarcodeLabel and BarcodePrinter classes allow displaying and printing EAN, UPC or QR barcodes.

BarcodeLabel:  QR barcodes

BarcodeLabel: QR barcodes

MindFusion WebForms DiagrammerMindFusion.Diagramming

Street maps
MapNodes can render street maps in OpenStreetMap format. Call FromXml method of MapContent to load an .osm file.

MindFusion WinForms  Street maps

MindFusion WinForms Street maps

Resize table columns and rows
Columns and rows of a TableNode can now be resized interactively if its AllowResizeColumns or AllowResizeRows properties are enabled. In order to resize, move the mouse pointer to the border line on column’s right side or row’s bottom side until it shows resize cursor and start dragging.

Barcode nodes
The BarcodeNode class displays EAN, UPC or QR barcodes as node’s content. In-place edit operations let users enter new numeric codes for 1D codes or text strings for QR codes.

Miscellaneous

  • Support for .NET 2 has been dropped; the minimum supported .NET framework version now is 3.5.
  • Distribution now includes a set of digitally-signed assemblies.
  • Undo/redo records for in-place edit operations are now created automatically. They are represented by instances of the EditTextCmd class.
  • CompositeNode supports vertical scrolling in EditComponent (only via keyboard).
  • Support for FromPage and ToPage properties of PrinterSettings .
  • CreateBarcodeNode methods added to the Factory class.
  • The BarcodeNodeStyle property of Diagram defines the default appearance of BarcodeNodes.
  • Improved speed when dragging large hierarchies of grouped nodes.
  • ZoomControl can now be used with other components by MindFusion and has been moved to MindFusion.Common.WinForms assembly and namespace.
  • and much more.

Map-16x16MindFusion.Mapping

Street maps
You can render street maps in OpenStreetMap format by adding a StreetMapLayer instance to the MapView. In order to load a street map, create a new StreetMapLayer > object and call its Map‘s LoadFromXml method to load the corresponding *.osm file.

Zoom control
The ZoomControl class lets user change interactively the current zoom level and scroll position of a MapView. To set it up, add a ZoomControl to the form, place it anywhere over a MapView, and set the control’s Target property to that view.

map-control-zooming

Multiple selection
Now it’s possible to select multiple decorations or map shapes by drawing a selection rectangle. To enable that, set the Behavior property to Select. Selected elements are stored in the Selection collection of respective layer objects.

API changes

  • The type of MapElement‘s Label property has been changed from string to Label class. The FontName and FontSize properties have been moved from MapElement to Label.
  • Type of Layers property changed from List to ObservableCollection .

WPF Reporting ToolMindFusion.Reporting

Barcodes
MindFusion.Reporting reports can now display UPC-A, UPC-E, EAN-8, EAN-13, and QR barcodes. The barcodes are represented by the new Barcode report item.

WinForms Reporter: Barcode Report Items

WinForms Reporter: Barcode Report Items

Miscellaneous

WebForms Scheduler by MindFusionMindFusion.Scheduling

Improved List View
The List view can now display an additional header and a footer. To turn them on, set the appropriate flag to the HeaderStyle property of the ListViewSettings class. The FooterFormat and MainHeaderFormat properties let you customize the text in the respective header. The text can also be customized through the CustomizeText event of the Calendar class. The size of the headers can be specified through the MainHeaderSize and FooterSize properties. Interactive Recurrence Rescheduling Recurrences can be rescheduled interactively by holding down the RescheduleRecurrenceKey while dragging a recurrent item. The control tries to preserve the current pattern of the recurrence when possible.

New Theme
A new built-in theme is available in MindFusion.Scheduling – the Light theme. It is available through the ThemeType enumeration.

The new 'Light' theme

The new ‘Light’ theme

New Properties
Several new properties have been added to the control:

Miscellaneous

Spreadsheet-16x16MindFusion.Spreadsheet

Autofiltering
Worksheets now support autofiltering. To enable it, call the AutoFilter method of the CellRange class. To specify autofiltering criteria for individual columns, use the AutoFilter overload.

WinForms Spreadsheet: Auto filtering

Multiple Selection
MindFusion.Spreadsheet now supports selection of multiple cell ranges. Cell ranges can be added to the selection interactively, by holding down the CTRL key while dragging with the mouse, or programmatically, by using one of the new methods of the Selection class: Add, AddRow, and AddColumn.

Miscellaneous

Installer for the latest version can be downloaded at https://www.mindfusion.eu/WinFormsTrial.zip

Updated assemblies are also available as MindFusion.Pack NuGet package.

About MindFusion.WinForms Pack: A set of five WinForms programming components that provide your application with a rich choice of diagramming, charting, scheduling, mapping, reporting and gauge features. The tools are very easy to implement and use. They boast intuitive API and various step-by-step tutorials to get you started. Both online and offline documentation is available.

A sample browser presents you with all the samples for each control to let you easily navigate to what you need. You can check some of the features of each component right now if you look at the online demos:

Visit the features – page of the components for more information about their capabilities:

You can check the prices and licensing scheme here. All components are royalty-free.

A Bar Chart With Multiple Axes and a Legend in WPF

In this post we will create a bar chart with multiple series and two Y-axes. We will do this exclusively in XAML, with the only exception a small code snippet that assigns one of the Y-axis to one of the bar series.

I. Setup of the Project.

We create a new WPF project. The necessary libraries are MindFusion.Charting.Wpf and MindFusion.Licensing. You can add them manually or drag the Bar chart control from the Visual Studio toolbox. In both cases your Window tag should have:

 xmlns:my="clr-namespace:MindFusion.Charting.Wpf;assembly=MindFusion.Charting.Wpf" 

Then we create the bar chart. If you’ve dragged the bar chart control the XAML code has been auto generated.

<my:barchart bartype="Vertical" title="Product Statistics" name="barChart">  
</my:barchart>

II. The Axes

The chart has two Y-axes. We create a new AxesCollection and assign it to the YAxes property:

<my:barchart.yaxes>
     <my:axescollection>
         <my:axis horlabelalignment="Left" titleoffset="10" minvalue="0" maxvalue="80" tick="2" title="Cost of Raw Materials" titlerotationangle="270" interval="8" labeltype="AutoScale">
          </my:axis>
  </my:axescollection>
</my:barchart.yaxes>

Let’s explain the code above line by line. First, the HorLabelAlignment property specifies how the labels will be aligned relative to the axis. If this was an Y2-axis, we would need to set the property to “Right”. Since this is an Y-axis and we want the labels to appear left to the axis, we align them “Let”. The TitleOffset, TitleRotationANgle and Title properties all specify how the label appears – it has an offset of 10 pixels measured from the longest label at the axis (if present). It is rotated so that it doesn’t take much space and its value is “Cost of Raw Materials”.

The MinValue, MaxValue and Interval properties define the axis – it’s start and end values and the span between each pair of adjacent intervals. Tick specifies the length of the ticks – the small lines drawn at each interval point. You can hide them by setting the Tick property to 0.

Finally, the LabelType property. It takes one of the LabelType enumeration values and sets what kind of labels will be drawn at the axis. This Y-axis will show the scale labels.

Then, we add the code for the second Y-axis. We just place the following XAML:

<my:axis horlabelalignment="Left" labels="{StaticResource YLabels}" titleoffset="10" minvalue="0" maxvalue="10" title="Marketing Costs" titlerotationangle="270" interval="1" tick="2" customlabelposition="AutoScalePoints" labeltype="CustomText">
     </my:axis>   

Most of the properties are the same as with the previous axis. The first difference is the value of the LabelType property. “Custom Text” means we will provide the labels for the axis. We create them as a static resource of strings:

<x:array x:key="YLabels" type="sys:String">
        <sys:string>0%</sys:string>
        <sys:string>7%</sys:string>
        <sys:string>6.5%</sys:string>
        <sys:string>6.3%</sys:string>
        <sys:string>6.2%</sys:string>
        <sys:string>5.8%</sys:string>
        <sys:string>5.5%</sys:string>
        <sys:string>5.1%</sys:string>
        <sys:string>4.9%</sys:string>
        <sys:string>4.5%</sys:string>
        <sys:string>4.2%</sys:string>
     </x:array>

Then we assign them to the Labels property. The CustomLabelPosition defines where the labels will be drawn – at the position of the data points of the series, bound to this axis or at the intervals of the auto scale. In this case we render the labels at the auto scale points.

The X-axis is defined similarly:

<my:barchart.xaxes>
     <my:axescollection>
       <my:axis labels="{StaticResource XLabels}" titleoffset="10" minvalue="0" maxvalue="6" title="Month" interval="1" customlabelposition="ChartDataPoints" labeltype="CustomText">
       </my:axis>
      </my:axescollection>
   </my:barchart.xaxes> 

The notable difference here is that we want the labels to appear at the location of chart data. That is why we will need to add a few lines of code later. But now let’s move to the series.

III. The Series

The series in this sample are two. Here is the markup for the first one:

<my:barseries xdata="1, 2, 3, 4, 5, 6" ydata="23, 34, 12, 45, 77, 19" fills="{StaticResource BrushCollection1}" title="Shoes" tooltiptype="ChartData">
     <my:barseries.effect>
           <dropshadoweffect shadowdepth="3" opacity="0.7">
     </dropshadoweffect></my:barseries.effect>
   </my:barseries>

The series are added directly within the tag, because Series is the default content property of the chart control. The Title, though not visible at the series itself is important for the legend as we will see later. The fills for the series are a collection of brushes, which we have defined as a static resource just like we defined the labels. The data for the series is set with the XData and YData properties. We add a visual effect to make the chart more appealing.

The second series is similar to this one, so we won’t deal with it now.

IV. The Legend

The control supports unlimited number of legends. They are of two types – SeriesLegend and ChartLegend. In our case we use the ChartLegend. This legend defines the legend labels and brushes based on a list of ChartSeries, that were assigned to it. Both types of legends are ItemsControl-s.

<my:barchart.legends>
  <my:chartlegend x:name="Legend" background="#FFFAFAFA" my:layoutpanel.dock="Bottom" orientation="Horizontal" horizontalalignment="Center" margin="5" cornerradius="5" borderthickness="1" borderbrush="#FFCECEFF" itemssource="{Binding ElementName=barChart}">
     <my:chartlegend.effect>
          <dropshadoweffect shadowdepth="3" opacity="0.7">
     </dropshadoweffect></my:chartlegend.effect>
   </my:chartlegend>
 </my:barchart.legends>

As you can see, the ItemsSource for the legend is the chart. This means it takes all ChartSeries, which are the default content property of the chart and renders their labels.

V. Binding the X-Axis to a ChartSeries

As you might remember the custom labels at the X-axis are bound to the location of the chart data. This means, we must tell the ChartSeries that it should use exactly the X-axis where we want the labels to appear. This is done with the ChartSeries.XAxis property. We do this in the code behind file.

   if (barChart.XAxes.Count > 0 && barChart.Series.Count > 0)
    {
       Axis xAxis = barChart.XAxes[0];
       BarSeries series = (BarSeries)barChart.Series[0];

       series.XAxis = xAxis;
    }

And this is everything. Here is the final chart:

WPF Chart Control: Bar Chart With Multiple Axes

WPF Chart Control: Bar Chart With Multiple Axes

The sample can be downloaded from here.

Learn more about MindFusion Chart Control for WPF here.

Charting for WPF, V2.0

The list below describes recent changes and additions to MindFusion.Charting for WPF:

Support for Multiple Axes

The chart can now render multiple axes at each side of the plot area. To enable that, add a new Axis instance to the XAxes collection properties for bottom axes, to YAxes collection for left-hand axes, and X2Axes / Y2Axes for respectively top and right sides. The old AxisSettings class and XAxisSettings / YAxisSettings objects have been removed, and now their properties are set independently for each Axis instance in the collections.

Multiple axes in the WPF chart control.

Multiple axes in the WPF chart control.

Improved Zooming

Selected area with width smaller than MinZoomSpan does not evoke any action in the control. In addition, the new ZoomChanged event fires whenever zoom occurs and provides useful data for the zoom action with its ZoomChangedArgs.

Cross Hair Improvements

The cross hair control has been improved with several new properties, a method and an event. The properties are:

The new CrossHairPosition method returns the current location of the cross hair. For more precise handling of cross hair movements a new event is available – CrossHairPositionChanged.

Cross hair is drawn in a WPF column chart.

Cross hair is drawn in a WPF column chart.

Greatly Improved 3D Charts

3D charts have received plenty of improvements, new properties and performance optimizations: PointMergeThreshold – The property sets the radius of an area around a given point where no other points are drawn. The result is better performance especially in charts with numerous points, which happen to be close to one another. Of points with similar coordinates only a single one is rendered, the rest are omitted.

InterpolationType.None – A new InterpolationType has been added to the InterpolationType enum, which does not interpolate but adds data directly and connects the points with triangulation.

The SurfaceType enum has been replaced with three bool properties, which makes the API easier to understand and use.

ScatterFaceSize – the property regulates the size of the polygons that build a 3D scatter. Bigger values lead to bigger polygons, which results in faster performance and rougher scatter mesh. Effect3D.ShaderEffect – the property can be applied to all 3D chart elements, including scatters and performs much faster.

3D surface chart with color map and wire frame.

3D surface chart with color map and wire frame.

Exporting Images

Two new methods have been added for exporting the chart as an image – CreateImage and ExportImage.

Custom Formatting of Labels in Real-time Charts

A new property has been added to the RealTimeChart library – Axis.LabelFormatProvider. Use it to specify custom formatting of numeric labels. If required, you can specify format arguments for your format classes with Axis.LabelFormat.

Direct download of the trial version is available from here:

Download MindFusion.Charting for WPF 2.0 Trial Version

You are welcome to contact us with any questions, problems or inquiries about the Charting for Wpf control or any other of our products. MindFusion has always put special emphasis on providing excellent customer support and we usually answer your inquiries in a few hours of receiving them.

About MindFusion.Charting for Wpf: A programming component that combines powerful charting capabilities with an elegant API and easy use. Among the features of the control are fully customizable grid, positive and negative values on all chart axes, 3D charts, gauges and many more – read a detailed list here.

The control provides detailed documentation and various samples that demonstrate how to customize every type of chart. It supports a wide range of 2D and 3D charts including bar, line, radar, bubble pie etc. You can add tooltips, define themes, perform hit testing, zoom and more.

ContainerNode fold / unfold animations

In this post we’ll show how to animate container’s fold and unfold operations using some event handling and custom drawing. You can download the complete project here:

AnimatedFold.zip

The sample code will demonstrate several features of the Diagram control and .NET:

  • use LINQ to collect contained items
  • handle fold/unfold events
  • custom draw from DrawForeground event
  • draw items from custom drawing code

Let’s start by creating some items and containers when the form loads:

private void Form1_Load(object sender, EventArgs e)
{
    var ctr = diagram.Factory.CreateContainerNode(20, 20, 100, 100, true);
    var node1 = diagram.Factory.CreateShapeNode(30, 35, 15, 15);
    var node2 = diagram.Factory.CreateShapeNode(80, 45, 15, 15);
    diagram.Factory.CreateDiagramLink(node1, node2);

    ctr.Add(node1);
    ctr.Add(node2);

    var ctr2 = diagram.Factory.CreateContainerNode(20, 20, 100, 100, true);
    ctr2.Add(ctr);
}

We’ll use LINQ extensions methods to find all items within a ContainerNode, including ones contained recursively in child containers:

List GetDescendents(ContainerNode container)
{
    var nodes = diagram.Nodes.Where(
        container.ContainsRecursively);

    var links = diagram.Links.Where(l =>
        nodes.Contains(l.Origin) ||
        nodes.Contains(l.Destination));

    return
        nodes.Cast().Concat(
        links.Cast()).ToList();
}

Add handlers for ContainerFolded and ContainerUnfolded events that will start animation for the container:

void OnContainerFolded(object sender, NodeEventArgs e)
{
    var container = (ContainerNode)e.Node;
    StartAnimation(container, true);
}

void OnContainerUnfolded(object sender, NodeEventArgs e)
{
    var container = (ContainerNode)e.Node;
    StartAnimation(container, false);
}

The StartAnimation method stores a list of items that should be redrawn during animation and a few other animation attributes:

void StartAnimation(ContainerNode container, bool fold)
{
    var bounds = container.Bounds;
    var scaleCenter = new PointF(
        (bounds.Left + bounds.Right) / 2, bounds.Top);

    // collect items that will be unfolded
    animatedItems = GetDescendents(container);

    // animation will also draw this rectangle as background
    ctrBounds = bounds;
    ctrBounds.Size = container.UnfoldedSize;
    ctrBounds.Y += container.CaptionHeight;
    ctrBounds.Height -= container.CaptionHeight;

    // start animation timers
    Animate(scaleCenter, fold);

    if (!fold)
    {
        // temporarily fold back when animating unfold operation
        // so that contained items stay invisible
        container.Folded = true;
        toUnfold = container;
    }
}

The Animate method starts a timer whose Tick event invalidates the DiagramView and stops the timer when final frame has been reached:

void Animate(PointF scaleCenter, bool scaleDown)
{
    if (scaleDown)
    {
        frameCounter = maxFrames;
        frameIncrement = -1;
    }
    else
    {
        frameCounter = 0;
        frameIncrement = +1;
    }
    this.scaleCenter = scaleCenter;

    animationTimer = new Timer();
    animationTimer.Tick += OnAnimationTimer;
    animationTimer.Interval = duration / maxFrames;
    animationTimer.Start();
}

void OnAnimationTimer(object sender, EventArgs e)
{
    frameCounter += frameIncrement;
    diagramView.Invalidate();
    if (frameCounter == 0 || frameCounter == maxFrames)
    {
        animationTimer.Stop();
        animationTimer.Dispose();
        animationTimer = null;
        animatedItems = null;

        if (toUnfold != null)
        {
            toUnfold.Folded = false;
            toUnfold = null;
        }
    }
}

Add a DrawForeground event handler that applies scale transform proportional to current frame of animation and draws the container’s descendants stored in animatedItems list:

void OnDrawForeground(object sender, DiagramEventArgs e)
{
    if (animatedItems != null && frameCounter > 0)
    {
        var options = new RenderOptions();
        var g = e.Graphics;

        // apply scale corresponding to current frame
        var scale = (float)frameCounter / maxFrames;
        g.TranslateTransform(scaleCenter.X, scaleCenter.Y);
        g.ScaleTransform(scale, scale);
        g.TranslateTransform(-scaleCenter.X, -scaleCenter.Y);

        // draw container background
        g.FillRectangle(Brushes.White, ctrBounds);
        g.DrawRectangle(Pens.Black, ctrBounds);

        // draw contained items
        foreach (var item in animatedItems)
            item.Draw(e.Graphics, options);
    }
}

Same technique can be applied to animate collapse and expand operations on tree branches. To implement that, handle NodeExpanded and NodeCollapsed events instead, and collect items reachable recursively from the branch’ root by following outgoing links.

The code above uses MindFusion’s .NET API and can be used with Windows Forms, WPF, Silverlight and ASP.NET diagramming components. The Java API for Android and desktop Swing application will look similar, with setter method calls instead of property assignments.

You can download the trial version of any MindFusion.Diagramming component from this page.

Enjoy!

Line Chart With Multiple Axes in WPF

A common scenario when building charts is the ability to render multiple series bound to multiple axes, each one with its own scale. To deal with this issue, MindFusion.Charting for WPF control has added support for multiple axes of all types – X, Y, Y2, X2 and in this post we’ll look how to add and customize them and how to create series bound to a given axis.

The sample imitates a production chart, where three different scales measure three different values – work output, capital and energy consumption – all of which presumably participate in producing a single unit of a product. On the right side we have a single Y2 axis, which measures the amount of units produced. The X-axis displays the time scale. Let’s look at the chart elements, one by one.

I. The Y-Axes

The Y-axes, as all axes in the chart are an instance of the Axis class and are added to the appropriate collection property. The Axis class defines all types of useful properties needed to customize an axis. We define the three axes in XAML:

<chart:linechart.yaxes>
    <chart:axescollection>
        <chart:axis minvalue="0" interval="5" maxvalue="60" labelformat="F0" tick="3" title="kWh/day" titlerotationangle="270" labelstroke="Red" titlestroke="Red"></chart:axis>
        <chart:axis minvalue="0" interval="300" maxvalue="2100" title="Capital (USD)" tick="3" titlerotationangle="270" labelstroke="Purple" titlestroke="Purple"></chart:axis>
        <chart:axis minvalue="100" interval="2.5" maxvalue="130" title="Work Productivity (%)" customlabelposition="AutoScalePoints" axiscrossingpoint="100.0" labeltype="CustomText" tick="3" titlerotationangle="270" labelstroke="Green" titlestroke="Green"></chart:axis>
    </chart:axescollection>
</chart:linechart.yaxes>

The property names easily describe what is set: the minimum and maximum values on each of the three axes, the title, the stroke for the labels and the title, the interval and the length of the axis ticks. Let’s note that the type of labels for the last Y-axis is “CustomText” – this means we will specify the labels explicitly rather than allow the control to generate them as with the other two axes – they don’t set a label type and the default value (the auto scale) is rendered.

Here is how we define the labels:

double start = 100.0;

    //130 is the last number at the axis
    while (start <= 130)
    {
        string l = start.ToString("F1") + "%";
        chart.YAxes[2].Labels.Add(l);
        start += 2.5;
    }

II. The Y2 Axis

The Y2-axis is just one and it is entirely declared in XAML:

<chart:linechart.y2axes>
    <chart:axescollection>
        <chart:axis minvalue="0" interval="1000" maxvalue="12000" tick="3" labelformat="F0" titlerotationangle="270" title="Units"></chart:axis>
     </chart:axescollection>
</chart:linechart.y2axes>

The label format is set with the standard .NET numeric strings – in this case it is a floating number without trailing zeros. In this axis, as well in the other Y-axes you might have noticed that we use the TitleRotationAngle property. This property rotates the title label at an arbitrary angle between 0 and 360. In our case we want the label drawn vertically, to conserve space.

III. The Series

The series are created in code. They specify scatter type because we want each series to have markers at data points. The YAxis property specifies the Y-axis, which a given Series is bound to. Finally, we specify the tool tip type because we want to have a tool tip when the mouse hovers a data point.

 LineSeries series0 = new LineSeries();
 series0.YAxis = chart.YAxes[0];
 series0.ScatterType = ScatterType.Square;
 series0.ScatterFills = new BrushCollection() { Brushes.Pink };
 series0.ScatterStrokes = new BrushCollection() { Brushes.Red };
 series0.Strokes = new BrushCollection() { Brushes.Red };
 series0.ToolTipType = ToolTipType.ChartData;

The data is random generated numbers. We use the Axis.XData and Axis.YData properties to set it.

 for (int i = 0; i < 30; i++)
     {
        series0.XData.Add(i * 6);
        data1.Add(rand.NextDouble() * 60.0);     
      }

      data1.Sort();
      series0.YData = new DoubleCollection(data1);
      //don't forget to add the series
      chart.Series.Add(series0);

Last but not least – don’t forget to add the series to the Series collection property of the chart. With that our chart is ready – here is the result:

Charting for WPF: Multiple Axes and Series

Charting for WPF: Multiple Axes and Series

You can download the sample with the chart libraries from here:

WPF Chart With Multiple Axes Sample Download

If you have any questions regarding the chart component use the forum, email or the help desk to contact MindFusion. More information about Charting for WPF, which includes a premium 3D charting library and a Real time charting library optimized to handle huge data sets can be found here.