Jump to content
Software FX Community
Sign in to follow this  
JuanC

Creating Win/Loss charts in WPF

Recommended Posts

Although Win/Loss charts can obviously be used to display win/loss/tie records they are also being increasingly used in dashboard scenarios to show a collection of values where there is a binary condition and you want to quickly see which values met such condition, e.g. to display a list of several products where you plot sales per month and want to easily see if the sales quota was met.

We will use as a sample and starting point a sparkline chart we created in this post, but will change the gallery to WinLoss and make sure we specify a goal for each product. If you do not specify a goal we will use 0 if there are positive and negative values or half the range if all values are positive/negative.

[color= blue]  <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.AllSeries[/color][color= blue]>    <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes[/color][color= blue]>      <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes.GalleryAttributes[/color][color= blue]>        <[/color][color= #a31515]cfxwinloss[/color][color= blue]:[/color][color= #a31515]WinLoss [/color][color= red]Goal[/color][color= blue]="30" />      </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes.GalleryAttributes[/color][color= blue]>    </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes[/color][color= blue]>  </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.AllSeries[/color][color= blue]>[/color]
[img=http://community.softwarefx.com/blogs/wpf/WinLoss1_thumb_4EC3F15B.png] 

The WinLoss gallery will try to choose a couple of colors in the current palette close to red and blue but you can assign precise colors by using the LossFill, LossStroke, WinFill and WinStroke properties. Additionally we can use ConditionalAttributes to color the biggest and smallest value, note that we use the AndCondition and MaximumValueCondition from the ChartFX.Data assembly, we use the AndCondition to make sure we only mark the biggest/smallest value if it was greater/smaller than the goal.

  [color= blue]<[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.AllSeries[/color][color= blue]>    <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes[/color][color= blue]>      <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes.GalleryAttributes[/color][color= blue]>        <[/color][color= #a31515]cfxwinloss[/color][color= blue]:[/color][color= #a31515]WinLoss [/color][color= red]Goal[/color][color= blue]="30"                            [/color][color= red]LossFill[/color][color= blue]="#FF8B89" [/color][color= red]LossStroke[/color][color= blue]="#FF8B89"                            [/color][color= red]WinFill[/color][color= blue]="#909090" [/color][color= red]WinStroke[/color][color= blue]="#909090"/>      </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes.GalleryAttributes[/color][color= blue]>    </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]AllSeriesAttributes[/color][color= blue]>  </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.AllSeries[/color][color= blue]>  <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.ConditionalAttributes[/color][color= blue]>    <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes [/color][color= red]Fill[/color][color= blue]="#007010" [/color][color= red]Stroke[/color][color= blue]="#007010">      <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes.Condition[/color][color= blue]>        <[/color][color= #a31515]cfxData[/color][color= blue]:[/color][color= #a31515]AndCondition[/color][color= blue]>          <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]RangeCondition [/color][color= red]From[/color][color= blue]="30"/>          <[/color][color= #a31515]cfxData[/color][color= blue]:[/color][color= #a31515]MaximumValueCondition[/color][color= blue]/>        </[/color][color= #a31515]cfxData[/color][color= blue]:[/color][color= #a31515]AndCondition[/color][color= blue]>      </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes.Condition[/color][color= blue]>    </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes[/color][color= blue]>    <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes [/color][color= red]Fill[/color][color= blue]="Red" [/color][color= red]Stroke[/color][color= blue]="Red">      <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes.Condition[/color][color= blue]>        <[/color][color= #a31515]cfxData[/color][color= blue]:[/color][color= #a31515]AndCondition[/color][color= blue]>          <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]RangeCondition [/color][color= red]To[/color][color= blue]="30"/>          <[/color][color= #a31515]cfxData[/color][color= blue]:[/color][color= #a31515]MinimumValueCondition[/color][color= blue]/>        </[/color][color= #a31515]cfxData[/color][color= blue]:[/color][color= #a31515]AndCondition[/color][color= blue]>      </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes.Condition[/color][color= blue]>    </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]ConditionalAttributes[/color][color= blue]>  </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.ConditionalAttributes[/color][color= blue]>[/color]

 

Posted Image

Finally, we will use WinLoss to show a new feature implemented in Chart FX for WPF which is also useful in bar charts when because of chart size, number of points or the combination of both generates thin bars, the issue is that we calculate sizes and positions using doubles, this allows WPF zoom and pixel independent architecture to work as expected but might generate an issue where the space between the bars is clearly not constant. For example if we now switch to 24 points per product and set the chart size to 120 pixels we might get something like this

Posted Image

A new property in PlotArea called PixelSnapMethod now supports three values:

  • None: Default value which uses double for all operations
  • Full: We make sure that the size of the bars and the space between them is constant, note that this might generate white space to the sides of the chart.
  • Marker: Space between bars is kept constant but size of the markers might vary slightly, this approach will not suffer from the same white space issue when using Full
  [color= blue]<[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.PlotArea[/color][color= blue]>    <[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]PlotAreaAttributes [/color][color= red]Margin[/color][color= blue]="0" [/color][color= red]AxesStyle[/color][color= blue]="None"                            [/color][color= red]Background[/color][color= blue]="{[/color][color= #a31515]x[/color][color= blue]:[/color][color= #a31515]Null[/color][color= blue]}" [/color][color= red]Stroke[/color][color= blue]="{[/color][color= #a31515]x[/color][color= blue]:[/color][color= #a31515]Null[/color][color= blue]}"                            [/color][color= red]PixelSnapMethod[/color][color= blue]="Full"/>  </[/color][color= #a31515]cfx[/color][color= blue]:[/color][color= #a31515]Chart.PlotArea[/color][color= blue]>[/color]

Posted Image

You can see all bars and white spaces sizes have been rounded to integers but because the number of pixels was not evenly divisible by the number of points there is some wasted space around the chart, if you switch PixelSnapMethod to Marker we will only make sure all spaces are the same, by making some bars wider than others it will not generate the empty areas around the plot area. Note that even though in this sample the space wasted by the Full method is not too bad, it could increase as the number of points increase.

Posted Image

JuanC

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...