BrownBot Logo BrownBot Head

Full Screen WPF App

6:43 pm Filed under: Uncategorized

Another quirk in WPF, apparently

<Window Title="MainWindow" WindowState="Maximized" WindowStyle="None">

Is not the same as

<Window Title=”MainWindow” WindowState=”Maximized” WindowStyle=”None” ResizeMode=”NoResize” >

With the former code, I got a full screen app that has a corrupt 1 – 2 pixel border down the far right hand side, this was throwing a spanning in the works for my “fly in” controls on the side.

Adding the “NoResize” fixed it right up.

WCF Callback Events in WPF Client and Console applications

11:06 pm Filed under: Uncategorized

WCF-WPF-Client-update-sampl Managed to pulled off some clever code today, got my callback events raised by a WCF service to safely manipulate the underlying ObservableCollections of my WPF client.

I’m sure it’s nothing that hasn’t been done before but I think my solution was quite graceful so I’ve put together a sample for people to use, something other than a chat program.

The image to the left shows 6 WPF clients with the same list of “BatchIDs” (ObservableCollection<string>), manipulating the list on any client re-arranges the list on the other clients.

Potential big concurrence issues I know but my implementation will only have one client with edit permissions, the others will have a read only view.

You can see the server which holds a master list of BatchIDs in the bottom left and a console client above it which simple lists out the sequence of BatchIDs when an update is received by the clients.

When one of the WPF clients completes a move within the list it sends it’s the sequence of BatchIDs up to the server, which in turn updates it’s master list and sends the list via callbacks down any other clients currently connected.

The WCF Contract is as follows:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IProductionReportingServiceCallback))]
public interface IProductionReportingService
{
    [OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)]
    bool Join(string name);

    [OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)]
    void NotifyBatchSeqenceUpdate(string[] batchIDSequence);

}

public interface IProductionReportingServiceCallback
{
    [OperationContract(IsOneWay = true)]
    void UpdateBatchSequence(string[] batchIDSequence);
}

the Join() is simply there for the server to store a callback for the client (List<IProductionReportingServiceCallback>), the NotifyBatchSequenceUpdate() is for clients to upload a new sequence.

The IProductionReportingServiceCallback is pretty self explanatory, it’s the callback sent down to the clients from the server.

 

I won’t bother explaining the implementation, you’ll have to look at the code and comments to work that out, but you use it as follows:

In your Main Window of your WPF app create the DuplexChannel so you can send a receive messages.

public staticProductionReportingServiceCallbackEventRaiser ProdRepSvcCallbackEvents;
public staticIProductionReportingService ProdRepSvc;

publicWindow1()
{
    // We pass in the Dispatcher here so the events come back to us on the UI thread
  
ProdRepSvcCallbackEvents = newProductionReportingServiceCallbackEventRaiser(Dispatcher);

    DuplexChannelFactory<IProductionReportingService> ProdRepSvcCF = newDuplexChannelFactory<IProductionReportingService>(
                                                  ProdRepSvcCallbackEvents,
                                                  newNetTcpBinding(),
                                                  newEndpointAddress(“net.tcp://localhost:9080/DataService”));

    ProdRepSvc = ProdRepSvcCF.CreateChannel();
    ProdRepSvc.Join(Environment.MachineName + “: WPFClient”);

    InitializeComponent();
}

We have the Service and Callback event wrapper as static so we can call/subscribe to them anywhere in the app like so:

Send up a new sequence

Window1.ProdRepSvc.NotifyBatchSeqenceUpdate(_batchList.ToArray());

Subscribe to the callback event

Window1.ProdRepSvcCallbackEvents.OnBatchSequenceUpdated += new EventHandler<UpdateBatchSequenceEventArgs>(OnBatchSequenceUpdated);

You can download the complete (server & client console class lib and WFP client) VS2008 project here (40k) enjoy!

Online Colour Wheel

8:42 pm Filed under: Uncategorized

ColourWheelFor anyone out there doing some design, be it a user interface, greeting card or painted master piece, the colour wheel is an invaluable tool for picking colours.

I was mucking about this morning cleaning up some rough edges in the UI design app I’m working on and stumbled across this great web based colour wheel.

I find it a great way to explore the colour spectrum looking for a list of complimentary colours.

As a bonus for the code monkeys out there that like to see there hexadecimal colours in code rounded out (ie #FFFF2255, I bet you also only ever set your stereo volume to numbers devisable by 2 or 5)  it limits the pallet to only round values.

As a bonus I also stumbled across this informative article on colour theory, handy for understanding how to use the colour wheel.

Fancy Options

8:27 pm Filed under: Uncategorized

With my app running on both sides now (Australia and South Africa), we needed an options control to easily check and edit the various defaults in the app.

Seeing it’s not something people have to look at all day every day I had a bit of a play with the styling to achieve something a bit more out there, it’s totally gratuitous so I didn’t spend a heap of time on it but am pretty happy with the result.

image

Handling application close from a user control in WPF

12:41 am Filed under: Uncategorized

Struck this one the other day and didn’t find a decent answer so here’s my solution.

I’ve got a user control or class that I want to have save one of it’s properties to the Settings.Settings on application shut down.  First thing you’ll find on a user control is that it doesn’t have an OnClose() or OnDispose() to override, lucky for us there’s an Exit event in Appliction.Current that we can subscribe to in our constructor instead.

He’s what it looks like…

public class ScheduleBuilder : INotifyPropertyChanged
{
    public ScheduleBuilder()
    {
        DetailWidth = Properties.Settings.Default.PreProdSchedDetailWidth;

        Application.Current.Exit += new ExitEventHandler(OnApplicationExit);
    }

    private int _detailWidth;

    public int DetailWidth
    {
        get
        {
            return _detailWidth;
        }
        set
        {
            if (value != _detailWidth)
            {
                _detailWidth = value;
                OnPropertyChanged("DetailWidth");
            }
        }
    }

    void OnApplicationExit(object sender, ExitEventArgs e)
    {
        Properties.Settings.Default.PreProdSchedDetailWidth = _detailWidth;
        Properties.Settings.Default.Save();
    }
}

One word of warning, be carefully doing this if you plan you use multiple instances of the class/control, you wont know which one will be that last one to save it’s value.

Bind to the width of a GridSplitter Column WPF

12:27 am Filed under: Uncategorized

Struggled with this one this afternoon, it seems a simple request, bind the width of a Grid Column to a value so it can be saved on program close and shared between Pages in a Navigation control.

The problem is that the width of a ColumnDefinition is not a simple value, it can be Auto, Star or Pixel value, Hence the binding kind of only works one way, I’m sure you could write a value converter to solve this as well but my simple solution is as follows.

XAML

<Grid DockPanel.Dock="Top">
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition Width="{Binding Path=DetailWidth, Mode=OneWay}/>
    </Grid.ColumnDefinitions>
    <Grid x:Name="ScheduleGrid" />
    <GridSplitter HorizontalAlignment="Right" VerticalAlignment="Stretch" Width="5" DragCompleted="GridSplitter_DragCompleted"/>
    <Grid Grid.Column="1" />
</Grid>

Code behind

private void GridSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
    DetailWidth = (int)((sender as GridSplitter).Parent as Grid).ColumnDefinitions[1].Width.Value;
}

The binding in the ColumnDefinition handles the get and we manually do the set in the event handler.

Expression Design

7:07 pm Filed under: Uncategorized

The latest beta of expression blend comes packaged with the full "Expression" suite of tools, I’ve been interested in checking out "Design" for some time to add some flare to my apps.

I’ve been playing around with it most of yesterday importing and animating a new loading control, this morning I got stuck into some vector images I need for my app, namely a pig and cow.

The results are below, anyone who’s got any proficiency in Photoshop or even old Corel draw will be right at home, it’s all splines and bezier curves. So far I’m impressed, it’s super easy to export from Design, add it to your project in Blend then drag them from the resource view into your button template or control.

VectorAnimals

Performance Issues

11:08 pm Filed under: Uncategorized

I’ve had performance issues with my new PC since day one, it’s been all over the place, one minute it’d rip a video at 45FPS next it’d be down to 2FPS, I was thinking it was heat related but sticking a fan in front of it didn’t help.

Next I reseated everything, no joy again. Today I got fed up with it and pulled out the video card, figured I’d try the most basic setup first, and low and behold it all started working well.

Who would have thought this intel integrated chip would be faster than an Nvidia card, it was some weird memory thing I think, anyhow it’s flying like a quad core should now, ripped the same video at just over 80FPS.

I quickly popped down to the place I bought the PC from to swap the video card over and he was busy unpacking a heap of new cards, said he’d have the prices ready for them tomorrow, might have to upgrade I think… those 8800 GTs look pretty good!

New Full Load Builder Interface

10:34 pm Filed under: Uncategorized

Following on from yesterday’s efforts, I’ve had a solid day on the rest of the load builder interface.

It’s not quite 100% finished yet, I’ve still a few buttons to re-style and I’ve got an idea for an animation to indicate the orders being inserted into a load which I’d like to try and implement.

This is what it use to look like:

WPFLoadBuilderUI-V1

Here’s what it looks like now:

WPFLoadBuilderUI V2

Much better!

WPF Group Container Styles

4:26 pm Filed under: Uncategorized

imageI’ve been trying to work out for a while now how to present data in the Group header of a CollectionViewSource.

All of the samples I’ve seen out on the web simply bind to the Name property and the ItemCount. After a bit of digging today I worked out how to Group on a common object property within a collection of objects, then borrow down into that object and bind to it’s properties from the group header.

Demonstrated in the picture above where I’m displaying a list of OrderItems (containing a product and amount) grouped by the Order (with the customer detail, delivery address etc) property they contain, then showing the order number and customer name in the group header.

I wasn’t very hard in the end so here we go, first up setup your CollectionViewSource to point to your ObjectDataProvider with some grouping etc etc as shown in this article.

Now assuming your PropertyGroupDescription is pointing to your object that is common across all the elements in the group (OrderItem.Order in my case).

<CollectionViewSource.GroupDescriptions>
    <PropertyGroupDescription PropertyName="Order"/>
</CollectionViewSource.GroupDescriptions>

You should be about to bind to the Objects properties like so.

<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
   <TextBlock Text="{Binding Path=Items[0].Order.Customer.Code, Mode=Default}"/>
   <TextBlock Text="{Binding Path=Items[0].Order.Customer.Name, Mode=Default}"/>
</StackPanel>

This is looking particularly handy for me as I can simply maintain a big list of OrderItem objects yet still render them as one Order.

« Previous PageNext Page »

Powered by WordPress