BrownBot Logo BrownBot Head

Taking Route Planning To The Next Level

3:37 pm Filed under: C#,Work,WPF

Some days I think I don’t have a bad handle on this WPF stuff, this weeks new route planning UI is some of my finest work yet. I can’t take all the credit though, Microsoft have done a stellar job with the Bing maps WPF control.

In the image below the days across the top of the map are actually a ListBox, the selected day brings forward and expands the order pins and lists the available trucks for that day. You simply drag the order from the map screen to the truck on the side to plot a route, you can even drag order items between trucks to re-route them.

RoutePlanning

I’ve still got a fair bit of detail to add and some more database fields to store the data, but most of technical hurdles have been overcome at this point. I’ll blog about a couple of tricky points I’ve hit soon.

Render a WPF Control On Reporting Services Report

12:15 am Filed under: C#,Work,WPF

I struck an issue this week where I need to display some ranged data in nice concise and easy to understand way on screen and on a report.  I tried graphing the data in Excel and a bar graph almost works but some of the data works back from 100% which won’t graph properly.

So today I set out to see if it was possible to render out a WPF control to an in memory byte[] on an extended “View” version of our Contract business object and bind an image to that property. After a lot of mucking about I finally got this.

 WPF control on reporting services report

Yep that’s a WPF button on an RS Report bound to an in memory object rendered on screen in the Winforms report viewer control.

Codewise it’s not that tricky really, if you follow the class below you can see how I render out the byte[] for the property in the constructor. We’re using VS2010 so you need to have your objects Serializable to use them in reporting services.

[Serializable]
    public class GrainPurchaseContractReportView : GrainPurchaseContract
    {
        public GrainPurchaseContractReportView(GrainPurchaseContract src)
        {
            // copy base class feilds here
            GenerateTestStandardGraph();
        }

        public GrainPurchaseContractReportView(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            _bmp = (Byte[])info.GetValue("StandardsGraph", typeof(Byte[]));
        }

        private Byte[] _bmp;

        public Byte[] StandardsGraph
        {
            get { return _bmp; }
        }

        private void GenerateTestStandardGraph()
        {
            BitmapEncoder encoder = new BmpBitmapEncoder(); 
            Button btn = new Button() 
            { 
                Content = "WPF",
                Height=40,
                Width=200
            };
            double dpi = 96;

            RenderTargetBitmap rtb = new RenderTargetBitmap(
                (Int32)(btn.Width * dpi / 96),
                (Int32)(btn.Height * dpi / 96),
                dpi,
                dpi,
                PixelFormats.Default);

            // Get the size of canvas
            Size size = new Size(btn.Width, btn.Height);

            // force control to Update
            btn.Measure(size);
            btn.Arrange(new Rect(size));

            rtb.Render(btn);

            using (MemoryStream ms = new MemoryStream())
            {
                encoder.Frames.Add(BitmapFrame.Create(rtb));
                encoder.Save(ms);
                _bmp = new byte[ms.Length];

                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(_bmp, 0, _bmp.Length);
            }

        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("StandardsGraph", StandardsGraph, StandardsGraph.GetType());
            base.GetObjectData(info, context);
        }
    }

The last part is to place an image on the report and use the “Database” source type and point it to your property.

WPF control on reporting services report image properties

Of course rendering a button on the report is not that handy, next I’ve got to build a user control that will render the actual data from our object.

New MilliT Home Page

9:17 pm Filed under: Work,WPF

Even though I’m nursing a sick baby today, I’ve managed to get those icons implemented into the admin program. I knocked up a custom ItemsControl with a BitmapImage and Title dependency properties, that has an Image with the TextBlock and a popup within the overwritten ControlTemplate.

The net result is the app “Home page” has gone from this horrible mess (Admittedly I let it get pretty bad because I knew it was going to be replaced):

MilliT-Before

To this:

MilliT-After

I also coloured and overlayed some stripes to the outer border, the stripes are a reference to the program icon and I think the colour helps separate the application controls from the content controls within the navigation pane.

I’m happy with the overall visual design of the MilliT app now, the weighbridge client needs a little attention next.

Purrrdy Icons

8:16 pm Filed under: Work,WPF

Having a fun day at work today knocking up some iPhone like icons for a new main menu screen in our administration app at the mill, MilliT. The plan is that the main screen will be an array of these icons, when you either hover over or click (not sure which yet) the icon you’ll see a popup with a list of app navigation links to click on.

Finance Production Pricing Products Contacts Contracts Deliveries

If I’ve done my job well you should be able to guess what each one if for, you can check by hovering over them.

I recon they hang together pretty well.

Weighbridge Remote Sync Console

9:21 pm Filed under: C#,WPF

After a mental but successful trip back to Australia to get the weighbridge client project up and running, I’m back in SA and working on the remote version of weighbridge.

The remote versions are going to run local SQL 2005 express with a 3G data connection to our VPN, so essentially they run the same as the directly connected version with an additional synchronization process to send/receive data to the main DB.

I was mucking about with this sync console today and was getting really variable performance (mostly really bad), one trend was that it would progressively slow down as it processed more jobs. The first version rendered a small grid showing the status of each job in a wrap panel.

SyncConsoleOriginal I had a brain wave this morning that all that rendering must be slowing it down, so I implemented a progress bar version.

SyncConsole Not only does it is look much nicer it runs about a million times faster, I’m not sure what WPF does with a wrap panel but it seems it might have been re-rending the whole thing every time a single item updated.

Today’s lesson: Be careful with large lists in WPF!

Popup With Shiny Black Reflection

7:50 pm Filed under: C#,Work,WPF

Easing myself back into work this morning with a few general updates around MilliT and the new Weighbridge client, there’s probably a hundred other more pressing jobs to do but I got side tracked with a little visual refresh of the hover over popup controls (which I blogged about some time ago http://www.brownbot.com/XNABlog/?p=325).

Here’s what they look like now, I think the black makes it really obvious that they’re separate to the rest of the app, the wanky iPhone like gradient adds some contemporary design fluff.

Popups

For any of you WPFers out there here’s the style code.

<LinearGradientBrush x:Key="PopupBorderGrad" StartPoint="0,0" EndPoint="1,0.2" >
    <GradientStop Color="#FF242424" Offset="0"/>
    <GradientStop Color="#FF383838" Offset="0.4"/>
    <GradientStop Color="#FF000000" Offset="0.401"/>
    <GradientStop Color="#FF000000" Offset="1"/>
</LinearGradientBrush>


<Style x:Key="PopupBorderStyle" TargetType="{x:Type Border}">
    <Setter Property="CornerRadius" Value="5,5,5,5"/>
    <Setter Property="BorderThickness" Value="0,1,0,0"/>
    <Setter Property="BorderBrush" Value="#FF888888"/>
    <Setter Property="Margin" Value="10,0,10,10"/>
    <Setter Property="Padding" Value="5,5,5,5"/>
    <Setter Property="Background" Value="{StaticResource PopupBorderGrad}"/>
    <Setter Property="SnapsToDevicePixels" Value="True" />
</Style>

Wizardry

5:10 am Filed under: C#,WPF

DelWiz1Had an awesome week of work last week, I finally started the actual Weighbridge client project that I’ve been working toward for the past six months. The guts of the client is the delivery wizard which guides the user through a series of steps to create one of the types of deliveries we receive in and out of the mill.

The steps and layout are defined by the old version of the client we’re replacing, the users are happy with it so I can’t stray too far from it, but that app was designed in the days of tiny screen resolutions. So problem number one was how to keep the layout roughly the same and cater for much higher res widescreen monitors.

The solution I came up with was to use Viewboxes to allow the user to choose their own zoom level and display the previous and next steps either side of the active step you’re filling out. So if you have trouble seeing you can have the single step filling up the whole screen, if you’ve got a massive monitor you can see what you’ve done in a previous step as you fill in the next step.

You also end up with a nice cover flow style and reflection look as well.


DelWiz2

I also came up with a nice little threaded class that takes an INotifyPropertyChanged object and property name, it monitors that property (using a little .Net reflection) for changes over a certain length and kicks off a search in a background thread. Perfect so little lookups and validation.

Those links you can see in the screen shot are little controls that you can hover over to see that object’s full details (in a popup), another benefit inherited from my previous viewmodel/view design.  In fact we should be able to directly link most of those views to the source files in the MilliT admin project.

It may have taken me all week to get one step done, but the major pieces are in place now so the rest of the wizard will be easy!

Sync Console Almost There

6:32 pm Filed under: C#,WPF

It’s been a pretty intense week on this Sync console upgrade, it’s coming together quite nicely even though I’ve had to add two additional object types (Customers and Suppliers) to sync. Kind of forgot that you can’t really sync the orders unless the customers are done first.

Not sure who would bother reading this but here’s a brief history of the app. It’s purpose is to import orders from our ERP software’s (SAGE) old school and very texty database design with very little input validation, over to our own in-house weighbridge system database.

V1

Version 1 didn’t actually look like anything, it was a scheduled series of SQL stored procs that fired off every 10 minutes.

The main problem with it was there was no way of warning the user if there was a problem with the order, so we wouldn’t know it had died till there was a truck waiting to leave with a load for the broken order.


SyncConsoleOldVersionVersion 2 moved it out to an application that the users could run at their leisure, it logged out all sorts of warnings and information that the users mostly ignore.

It still runs all sync tasks as one big batch though, there’s no way to cancel half way through or selectively sync a single item.

It served it’s purpose but is looking a little weathered.


SyncConsoleUpdates SyncConsoleWarning Version 3 is prettier, about a million times faster (due to using direct to DB providers rather than datasets and more intelligently selecting what to sync), fully threaded, cancellable and able to do a single item if you need.

Hopefully this version will last us a while… once it’s finished, still needs some more testing.

Order Sync Super Clean UI

8:11 pm Filed under: WPF

Here’s the first draft of the new order sync UI design, basically it has to preload either a single order (if there’s a number entered) or all active order numbers from SAGE, then individually load up the Weighbridge version, compare the two versions (checking the production status so we don’t change anything we shouldn’t), merge the two if everything looks ok then save the result back to the weighbridge.

If I’ve done my job right you should be able to guess the status of the different order sync operations (ie No change, updated, created etc). Each step in the operation returns a validation result (with an error message on failure) but can also log warning and informational messages via TRACE calls (basically console messages).  All these messages will be captured by a SyncOperation object which the list is bound to.

OrderSyncUI

I’m happy with the list view but not 100% on the detail view yet, I might revert back to bordered expanders like the other viewmodel stuff I’ve done. This was all done in Photoshop so it’ll mutate as I implement the WPF code.

MilliT – Sales Orders

11:33 am Filed under: C#,WPF

Here’s what I achieved this week, a new set of providers and read only UI for our sales orders.

None of it is particularly remarkable, but I’m happy that my MilliT view model client code doesn’t suck yet (all code will eventually suck, it’s just a mater of time), actually I find it quite a nice place to spend the day coding WPF. Only a day to fully lay out a snazzy looking UI like this is pretty cool I recon.

On the provider side (boring!), I’ve set out a nice standard structure for all these more complex hierarchical object providers, which will help me a lot when I tackle the big kahuna schedule objects next week.

MilliT-order-view

Next Page »

Powered by WordPress