Simon Taylor - .Net developer, Cheltenham

My record of coding problems solved and new things discovered

Using Lucene.NET with BlogEngine.NET

clock April 25, 2010 17:06 by author Simon

I've just changed the search functionality of this blog to use Lucene.NET and all of the quick, rich searching functionality that that provides. It is testament to whoever first wrote the original blog engine search functionality, that it was as relatively straight forward to do as it was. Below are the steps and an explanation of some of the code changes I made - I'm not going to explain what Lucene is or how it works, there are plenty of resources out there that alreday do this, just use your favourite search engine to find them. Smile More...



How NHibernate integrates with second level cache

clock April 23, 2010 01:03 by author Simon

It's never been 100% clear to me when using second level cache with NHibernate, when NHibernate accesses the cache and when it needs to go to the database directly. There is a great explanation of how NHibernate uses caching in The NHibernate FAQ, but even after reading this, I still wasn't completely clear on when NHibernate has to hit the database, so I went about testing it out myself. Below are the results of my testing; I was using NHibernate 2.1.2.400, FluentNHibernate 1.0.0.629, SQLServer 2008 and NCache 3.6. I created a single test consisting of each of the code snippets below and I set the NHibernate show_sql configuration parameter to true so that I could see when NHibernate hit the database. I also created an IClassConvention that tells NHibernate to cache all entities as read write (in reality I would probably be more granular than this). More...



Integrating with Microsoft Project Server 2007 (2)

clock August 13, 2009 18:42 by author Simon

I have already done one post on integrating with project server. Since then I have had to get much more involved with it and have discovered it's a bit of a dark art to say the least. Hopefully, this post will serve as a useful resource to anyone else who needs to do the same and stop them from having to go through all of the pain that I went through.Cry More...



Copying datarows

clock August 8, 2009 09:06 by author Simon

Some succinct code for making a copy of a row from a DataTable.More...



Creating classes at runtime

clock June 14, 2009 21:55 by author Simon

I've been working on an application that has a number of forms that need to be laid out based on configuration data in the database, this enables the application to meet the requirements of many different customers. Laying out the forms based on the configuration data is relatively trivial - it is just a matter of writing the code that normally ends up in the .designer file. However, because there could be any number of controls on the form, binding an object to them is a little more tricky. I approached this problem by creating a class that describes a control that will added to the form together with a boolean, integer and string value field that is used to initialise the control and capture the users input based on the type of control. I had a list of these objects representing all of the controls that needed to be rendered on the form, to bind the controls to these objects, I needed an adapter which I created at runtime.More...



Passing an IronPython method to a C# method that takes a delegate as a parameter

clock June 14, 2009 21:42 by author Simon

This is again IronPython 101, but again took me a little bit of time to work out how to do it. Consider the following C# delegate and method:More...



Encryptor

clock June 14, 2009 20:54 by author Simon

I've written an encryption utility that I find quite useful. There is nothing special about the code that does the encryption, but I have given it a command line interface and kept the actual encryption logic in a separate assembly which can be added to other applications. What I use this for is to manually encrypt data which I then put in a database which can then be decrypted by my application by adding a reference to the dll which has the encryption logic. More...



Using JSON.Net

clock June 14, 2009 20:12 by author Simon

I was involved in a project on a customers ASP.Net CMS to embed a flex application which enables the user to enter some parameters and see how they affect the results which are displayed in a stacked bar-chart. The formula's that are used to calculate the results are highly sensitive therefore the logic could not be embedded in the flex application, therefore the only alternative was to expose some .net web services to provide the functionality. Although the data that is returned by the web services is basic and fairly minimal, from my experience of using flex, I was concerned that this wouldn't be as straight forward as it seemed. One of my concerns about consuming .net web services with flex was whether Microsoft actually adhere properly to web service standards, therefore I decided to return the data as JSON. This would mean that we wouldn't be relying on Microsoft to properly adhere to web service standards and my colleague who was writing the flex application had experience of consuming JSON, albeit from web services written using Ruby.More...



A Stacked Bar Chart Silverlight control

clock May 3, 2009 11:01 by author Simon

EDIT: The Silverlight Toolkit now includes a stacked bar chart. A great blog post about it can be found on Delay's blog.

The Silverlight Toolkit provides developers and designers with a whole host of different controls that don't come as standard. Amongs other things it contains charting controls for creating bar charts, pie charts and line graphs etc. I recently had a requirement for a stacked bar chart which unfortunately is one of the few types of chart that isn't supported out of the box. However, after reading a series of posts written by Jafar Husain and taking a look at the toolkit source code I realised that I could create a stacked bar chart relatively easily myself - despite having only limited knowledge of Silverlight. At this point I have to appologise to Jafar - I asked his advice via his blog and he responded with a very comprehensive description of how he would go about tackling this problem. Jafar's approach would have produced a much more complete and flexible solution however, it was overkill for what I needed and I had to get something put together as quickly as possible, so I took an (arguably) more hacky approach.

The approach I took was to create a new StackedColumnSeries which was a total copy of the System.Windows.Controls.DataVisualization.Charting.ColumnSeries class. At this point it would have been great to have been able to use ColumnSeries as the base class for StackedColumnSeries, but because ColumnSeries is sealed I had to copy and paste instead. I had to copy and paste various other chunks of code from the toolkit as well, to get my copy of ColumnSeries to compile since various helper classes etc were internal. If you download the code you will see that I've clearly commented which bits of code I've copied, so if the toolkit team open up their code a bit more in the future it will be straight forward to change the StackedColumnSeries class.

Once the StackedColumnSeries class was compiling and functioning like the ColumnSeries I needed to make changes to just two methods to make it function like a stacked column chart. The methods that I changed were UpdateDataPoint(DataPoint dataPoint) so that columns could be rendered so that they appear stacked on top of each other and GetValueMargins(IValueMarginConsumer consumer) so that I could increase the range of values that appear on the axis taking into account the fact that the maximum value that needed to be displayed now needed to be the sum of the stacked columns.

The two changed methods are below - please see the comments in the code for the changes that I needed to make to the code that I copied from the ColumnSeries.

        /// <summary>
        /// Updates each point.
        /// </summary>
        /// <param name="dataPoint">The data point to update.</param>

        protected override void UpdateDataPoint(DataPoint dataPoint)
        {
            if (SeriesHost == null || PlotArea == null)
            {
                return;
            }

            object category = dataPoint.IndependentValue ?? (this.ActiveDataPoints.IndexOf(dataPoint) + 1);
            Range<UnitValue> coordinateRange = GetCategoryRange(category);
            if (!coordinateRange.HasData)
            {
                return;
            }
            else if (coordinateRange.Maximum.Unit != Unit.Pixels || coordinateRange.Minimum.Unit != Unit.Pixels)
            {
                throw new InvalidOperationException("This Series Does Not Support Radial Axes");
            }

            double minimum = (double)coordinateRange.Minimum.Value;
            double maximum = (double)coordinateRange.Maximum.Value;

            double plotAreaHeight = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum).Value.Value;
            IEnumerable<StackedColumnSeries> columnSeries = SeriesHost.Series.OfType<StackedColumnSeries>().Where(series => series.ActualIndependentAxis == ActualIndependentAxis);
            int numberOfSeries = columnSeries.Count();
            double coordinateRangeWidth = (maximum - minimum);
            double segmentWidth = coordinateRangeWidth * 0.8;

            // For stacked chart, no need to scale the width of the columns if there are more series

            double columnWidth = segmentWidth; // / numberOfSeries;
            int seriesIndex = columnSeries.IndexOf(this);

            double dataPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToDouble(dataPoint.ActualDependentValue)).Value.Value;
            double zeroPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Origin).Value.Value;

            // Need to shift the columns up to take account of the other columns that are already rendered, to make them

            // appear stacked
            int dataPointIndex = ActiveDataPoints.IndexOf(dataPoint);

            for (int i = numberOfSeries - 1; i > seriesIndex; i--)
            {
                StackedColumnSeries prevSeries = columnSeries.ElementAt<StackedColumnSeries>(i);

                if (prevSeries.ActiveDataPointCount >= dataPointIndex + 1)
                {
                    double yOffset = ActualDependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToDouble(prevSeries.ActiveDataPoints.ElementAt<DataPoint>(dataPointIndex).ActualDependentValue)).Value.Value;

                    dataPointY += yOffset;
                    zeroPointY += yOffset;
                }
            }

            // No offset for stacked bar charts so that all the columns line up

            double offset = 0; /*seriesIndex * Math.Round(columnWidth) + coordinateRangeWidth * 0.1;*/
            double dataPointX = minimum + offset;

            if (GetIsDataPointGrouped(category))
            {
                // Multiple DataPoints share this category; offset and overlap them appropriately
                IGrouping<object, DataPoint> categoryGrouping = GetDataPointGroup(category);
                int index = categoryGrouping.IndexOf(dataPoint);
                dataPointX += (index * (columnWidth * 0.2)) / (categoryGrouping.Count() - 1);
                columnWidth *= 0.8;
                Canvas.SetZIndex(dataPoint, -index);
            }

            if (ValueHelper.CanGraph(dataPointY) && ValueHelper.CanGraph(dataPointX) && ValueHelper.CanGraph(zeroPointY))
            {
                // Remember, the coordinate 0,0 is in the top telft hand corner, therefore the "top" y coordinate is going to

                // be a smaller value than the bottom.
                double left = Math.Round(dataPointX);
                double width = Math.Round(columnWidth);

                double top = Math.Round(plotAreaHeight - Math.Max(dataPointY, zeroPointY) + 0.5);
                double bottom = Math.Round(plotAreaHeight - Math.Min(dataPointY, zeroPointY) + 0.5);
                double height = bottom - top + 1;

                Canvas.SetLeft(dataPoint, left);
                Canvas.SetTop(dataPoint, top);
                dataPoint.Width = width;
                dataPoint.Height = height;
            }
        }

        /// <summary>

        /// Returns the value margins for a given axis.
        /// </summary>
        /// <param name="consumer">The axis to retrieve the value margins for.
        /// </param>
        /// <returns>A sequence of value margins.</returns>

        protected override IEnumerable<ValueMargin> GetValueMargins(IValueMarginConsumer consumer)
        {
            double dependentValueMargin = this.ActualHeight / 10;
            IAxis axis = consumer as IAxis;
            if (axis != null && ActiveDataPoints.Any())
            {
                Func<DataPoint, IComparable> selector = null;
                if (axis == InternalActualIndependentAxis)
                {
                    selector = (dataPoint) => (IComparable)dataPoint.ActualIndependentValue;

                    DataPoint minimumPoint = ActiveDataPoints.MinOrNull(selector);
                    DataPoint maximumPoint = ActiveDataPoints.MaxOrNull(selector);

                    double minimumMargin = minimumPoint.GetMargin(axis);
                    yield return new ValueMargin(selector(minimumPoint), minimumMargin, minimumMargin);

                    double maximumMargin = maximumPoint.GetMargin(axis);
                    yield return new ValueMargin(selector(maximumPoint), maximumMargin, maximumMargin);
                }
                else if (axis == InternalActualDependentAxis)
                {
                    // Some up the total value of the current set of columns

                    double valueTotal = 0.0;

                    foreach (DataPoint dataPoint in ActiveDataPoints.AsEnumerable<DataPoint>())
                    {
                        valueTotal += (double)dataPoint.ActualDependentValue;
                    }
                    // The minimum value always needs to be 0 for stacked column charts
                    yield return new ValueMargin(0.0, dependentValueMargin, dependentValueMargin);
                    yield return new ValueMargin(valueTotal, dependentValueMargin, dependentValueMargin);
                }
            }
            else

            {
                yield break;
            }
        }

The resut of running this code and and binding some data to the chart can be shown below (notice I have also added a line series).

Staked Bar Chart

NOTE: It has come to my attention that there are a couple of minor bugs with this solution, for example some parts of the chart don't lose their selected state. Unfortunately, as the control met my requirements, it is unlikely that I am going to get chance to investigate these bugs now. Hopefully, the information in the post above is detailed enough to show people how I arrived at my solution and be a good starting point for debugging and fixing any problems.



IronPython - a configuration language

clock April 8, 2009 19:35 by author Simon

I had a requirement to create a state machine for a product at work. The product is a project management tool and therefore has the concept of a job which based on the users actions moves from one state to another. There was also the additional requirement that the state machine should be configurable by/for different customers. Esentially, the state machine is a large flow diagram but the implementation needed to allow for completely ripping up the first customers flow diagram and replacing it with a completely different one for the next customer.More...



About the author

Simon is currently living and working in Toronto, Canada as a software consultant for Infusion. He is primarily a .Net developer although sometimes has to turn his hand to other technologies such as Java and flex. Simon has also recently started iPhone application development. Contact me.

Sign in