Quantcast
Channel:
Viewing all 24 articles
Browse latest View live

MDI in WPF via Dragablz

$
0
0

Dragablz is more than just a Chrome style TabControl for WPF.  Via it’s Layout control it provides docking and tool windows.  Taking the tool windows a step further, they can be used to provide an MDI effect in WPF.  Even better, the MDI environment can reside inside a tab, which, when coupled with Dragablz other tear out and docking features can provide very rich UI Window management for the user.

There’s a couple of properties of the Layout control to consider:

  • FloatingItems – allows any items to be floated on top of the Layout’s content.
  • FloatingItemsSource – allows any items to be floated on top of the Layout’s content.

And a selection of RoutedCommand’s to help out with management of items floated on the Layout:

  • UnfloatItemCommand –
  • MaximiseFloatingItem
  • RestoreFloatingItem
  • TileFloatingItemsCommand
  • TileFloatingItemsVerticallyCommand
  • TileFloatingItemsHorizontallyCommand

Here’s a snippet of an MDI layout from the Dragablz demo on GitHub:

<DockPanel>
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
        <Button Command="{x:Static dockablz:Layout.TileFloatingItemsCommand}"
                CommandTarget="{Binding ElementName=MdiLayout}">Tile Grid</Button>
        <Button Command="{x:Static dockablz:Layout.TileFloatingItemsVerticallyCommand}"
                CommandTarget="{Binding ElementName=MdiLayout}">Tile Horizontal</Button>
        <Button Command="{x:Static dockablz:Layout.TileFloatingItemsHorizontallyCommand}"
                CommandTarget="{Binding ElementName=MdiLayout}">Tile Vertical</Button>
    </StackPanel>
    <dockablz:Layout x:Name="MdiLayout" 
                     FloatingItemHeaderMemberPath="Name"
                     FloatingItemDisplayMemberPath="SimpleContent">            
        <dockablz:Layout.FloatingItems>                
            <dragablzDemo:SimpleViewModel Name="One" SimpleContent="MDI Child One" />                
            <dragablzDemo:SimpleViewModel Name="Two" SimpleContent="MDI Child Two" />                
            <dragablzDemo:SimpleViewModel Name="Three" SimpleContent="MDI Child Three" />
        </dockablz:Layout.FloatingItems>
    </dockablz:Layout>
</DockPanel>

And to illustrate what’s achievable, here’s an MDI layout, inside a tear-able tab:

MDI, operating within a tab.
MDI, operating within a tab.

Links to Dragablz:



How to use the Material Design theme with Dragablz Tab Control

$
0
0

In this post I will demonstrate how to – very quickly – combine Dragablz and MaterialDesignColors in WPF to create a great looking control which supports full tear out and can use the Google Material Design colour palette.

Dragablz Tab Contrtol and Material Design
Dragablz Tab Contrtol and Material Design

Start a new WPF project.  We rely on two NuGet packages, so get them installed straight away.  Install from the Package Manager tool in Visual Studio, or, from the NuGet console run these commands:

Install-Package Dragablz
Install-Package MaterialDesignColors

In the MainWindow.xaml, setup a simple usage of Dragablz TabablzControl:

<Window x:Class="MaterialDesignTabExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
        Title="Material Design Demo" Height="350" Width="525">
    <dragablz:TabablzControl>
        <dragablz:TabablzControl.InterTabController>
            <dragablz:InterTabController />
        </dragablz:TabablzControl.InterTabController>
        <TabItem Header="HELLO">
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Hello World</TextBlock>
        </TabItem>
        <TabItem Header="MATERIAL">
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Material Design</TextBlock>
        </TabItem>
        <TabItem Header="DESIGN">
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Looks Quite Nice</TextBlock>
        </TabItem>
    </dragablz:TabablzControl>
</Window>

Already if you run this project you will have a tab control that supports Chrome-style tearing out of tabs. But it wont look too good. So, the next step is to bring in the Material Design colours, and tell Dragablz to use the Material Design style.

Open up your App.xaml. We have to merge in three dictionaries.  The first two are to set up your Material Design colour palette.  The MaterialDesignColors assembly contains a ResourceDictionary for each color (a collection of hues and accents).  To create a full palette we need to bring in a primary colour, set up some hue brushes, and then bring in a secondary color for our accent color.  The third resource dictionary is to include the Dragablz theme for Material Design.  Finally we instruct our tab control to use the correct style.

Don’t worry, it’s not too complicated.  The full App.xaml is below:

<Application x:Class="MaterialDesignColors.WpfExample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <!-- primary color -->
                <ResourceDictionary>
                    <!-- include your primary palette -->
                    <ResourceDictionary.MergedDictionaries>
                        <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Indigo.xaml" />
                    </ResourceDictionary.MergedDictionaries>
                    <!--
                            include three hues from the primary palette (and the associated forecolours).
                            Do not rename, keep in sequence; light to dark.
                        -->
                    <SolidColorBrush x:Key="PrimaryHueLightBrush" Color="{StaticResource Primary100}"/>
                    <SolidColorBrush x:Key="PrimaryHueLightForegroundBrush" Color="{StaticResource Primary100Foreground}"/>
                    <SolidColorBrush x:Key="PrimaryHueMidBrush" Color="{StaticResource Primary500}"/>
                    <SolidColorBrush x:Key="PrimaryHueMidForegroundBrush" Color="{StaticResource Primary500Foreground}"/>
                    <SolidColorBrush x:Key="PrimaryHueDarkBrush" Color="{StaticResource Primary700}"/>
                    <SolidColorBrush x:Key="PrimaryHueDarkForegroundBrush" Color="{StaticResource Primary700Foreground}"/>
                </ResourceDictionary>

                <!-- secondary colour -->
                <ResourceDictionary>
                    <!-- include your secondary pallette -->
                    <ResourceDictionary.MergedDictionaries>
                        <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/MaterialDesignColor.Yellow.xaml" />
                    </ResourceDictionary.MergedDictionaries>

                    <!-- include a single secondary accent color (and the associated forecolour) -->
                    <SolidColorBrush x:Key="SecondaryAccentBrush" Color="{StaticResource Accent200}"/>
                    <SolidColorBrush x:Key="SecondaryAccentForegroundBrush" Color="{StaticResource Accent200Foreground}"/>
                </ResourceDictionary>

                <!-- Include the Dragablz Material Design style -->
                <ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/materialdesign.xaml"/>                

            </ResourceDictionary.MergedDictionaries>

            <!-- tell Dragablz tab control to use the Material Design theme -->
            <Style TargetType="{x:Type dragablz:TabablzControl}" BasedOn="{StaticResource MaterialDesignTabablzControlStyle}" />
        </ResourceDictionary>
    </Application.Resources>
</Application>

And that’s it. Fire up your baby and you are done. You can change the colours by changing the two colour resource dictionaries which are referenced. You can also tweak the hues, but do not change the brush names.  Dragablz will be looking for these.

Links:

Enjoy!


Dragablz Meets MahApps, pt II.

$
0
0

In a previous post I showed Dragablz and MahApps working together with a few basic pointers.  In this post I will illustrate the specific MahApps styles included in Dragablz, and show how to get a basic app shell up and running using both libraries.

So, starting from scratch, create a new WPF Application in Visual Studio.  Throw a TabControl into your app.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
        Title="MainWindow" Height="350" Width="525">
    <TabControl>
        <TabItem Header="One">
            <Button HorizontalAlignment="Center" VerticalAlignment="Center">Hello World</Button>
        </TabItem>
        <TabItem Header="Two">
            <Button HorizontalAlignment="Center" VerticalAlignment="Center">How are you doing</Button>
        </TabItem>
        <TabItem Header="Three">
            <Button HorizontalAlignment="Center" VerticalAlignment="Center">Goodbye</Button>
        </TabItem>
    </TabControl>
</Window>

If you fire it up, you’ll see it looks like tripe. And it’s static. To bring the tab control to life get Dragablz installed. Either from the Package Manager Console or the Manage Nuget Packages dialog install Dragablz.

Install-Package Dragablz

Switcheroo our boring old TabControl to the TabablzControl, and add an InterTabController property to let Dragablz know that the user can tear tabs out:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
        Title="MainWindow" Height="350" Width="525">
    <dragablz:TabablzControl>
        <dragablz:TabablzControl.InterTabController>
            <dragablz:InterTabController />
        </dragablz:TabablzControl.InterTabController>
        <TabItem Header="One">
            <Button HorizontalAlignment="Center" VerticalAlignment="Center">Hello World</Button>
        </TabItem>
        <TabItem Header="Two">
            <Button HorizontalAlignment="Center" VerticalAlignment="Center">How are you doing</Button>
        </TabItem>
        <TabItem Header="Three">
            <Button HorizontalAlignment="Center" VerticalAlignment="Center">Goodbye</Button>
        </TabItem>
    </dragablz:TabablzControl>
</Window>

If you fire up the application now you should be able to tear the tabs out.

But it most definitely still looks rubbish. We need styles. Again, use your NuGet delivery mechanism of choice to bring in MahApps.Metro.

Install-Package MahApps.Metro

MahApps handy QuickStart guide should popup in Visual Studio. If it doesn’t, check here.  Follow the guide.  In summary we need to convert our Window to the MetroWindow, and add a include few ResourceDictionary instances in the App.xaml.

Fire the application up, take a look.  Things are improving:

MahApps Window with default-styled TabablzControl
MahApps Window with default-styled TabablzControl

We have a metro/modern UI Window and button.  But the tab control is yet to receive a makeover. You should already made the relevant MahApps ResourceDictionary inclusions in the App.xaml. Now we need to bring in the Dragablz ResourceDictionary which contains the MahApps styles, and specify the default style for the DragablzTabControl, giving you an App.xaml which looks like:

<Application x:Class="DMGMD.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
                
                <ResourceDictionary Source="pack://application:,,,/Dragablz;component/themes/mahapps.xaml" />
            </ResourceDictionary.MergedDictionaries>
            
            <Style TargetType="{x:Type dragablz:TabablzControl}" BasedOn="{StaticResource MahAppsTabablzControlStyle}" />
            
        </ResourceDictionary>
    </Application.Resources>
</Application>

If you fire up the application you will see the tab control is now coloured according to the MahApps accent defined in the App.xaml.

MahApps Window with themed TabablzControl
MahApps Window with themed TabablzControl

As a bonus, let’s add a Dragablz tool window to the Window, which can also be themed with MahApps colours. Switch back to MainWindow.xml, wrap the TabablzControl in a Layout (notice the FloatingItemContainerStyle property), and add a simple floating item to the Layout:

<controls:MetroWindow x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz"
        xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
        xmlns:dockablz="clr-namespace:Dragablz.Dockablz;assembly=Dragablz"
        Title="MainWindow" Height="350" Width="525">
    <dockablz:Layout FloatingItemHeaderMemberPath="Header" FloatingItemDisplayMemberPath="Content"
                     FloatingItemContainerStyle="{DynamicResource MahAppsToolDragablzItemStyle}">
        <dockablz:Layout.FloatingItems>
            <dragablz:HeaderedItemViewModel Header="Tool Window" Content="Tool window shich is also themed!" />
        </dockablz:Layout.FloatingItems>
        <dragablz:TabablzControl>
            <dragablz:TabablzControl.InterTabController>
                <dragablz:InterTabController />
            </dragablz:TabablzControl.InterTabController>
            <TabItem Header="One">
                <Button HorizontalAlignment="Center" VerticalAlignment="Center">Hello World</Button>
            </TabItem>
            <TabItem Header="Two">
                <Button HorizontalAlignment="Center" VerticalAlignment="Center">How are you doing</Button>
            </TabItem>
            <TabItem Header="Three">
                <Button HorizontalAlignment="Center" VerticalAlignment="Center">Goodbye</Button>
            </TabItem>
        </dragablz:TabablzControl>
    </dockablz:Layout>
</controls:MetroWindow>

And here will be your final result, a MahApps Window, ready for all your Metro/Modern UI content, which can also support tear-able tabs, tool windows, and docking!

dragablzandmahappstutorial_03

In a future post I will illustrate how to add and remove tabs, and work in a MVVM environment.


Material Design In XAML – Mash Up!

$
0
0

I have previously posted about the Material Design theme for Dragablz.  In this post I will describe how I arrived at this application mock-up, by combining Dragablz, Material Design in XAML Toolkit, and MahApps:

Material Design Demo
Material Design Demo

My initial task when creating that style was to create a separate, and composable way to define the Material Design colour palette for your application.  Making the separation between the colours and the Dragablz Material Design theme immediately paid benefit.  Being a big fan of MahApps and I was easily able to take things a step further and use the palette in conjunction with a MahApps MetroWindow. Encouraging MahApps to pick up my Material Design palette turned out to be easy because of the way the MahApps guys had also separated out their accents.  Very quickly, I had a MahApps MetroWindow up and running, using MahApps themed controls, the Dragablz Material Design theme, and all of which were using the Material Design palette.  It looked pretty good straight away.

I’ve previously posted on how to choose a Material Design palette, but for a refresher, take a look at this App.xaml.

In addition to the Material Design palette, you need to set a base theme; light or dark.  So add this resource dictionary to your App.xaml:

<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />  

Getting MahApps to use the Material Design palette only takes a few extra lines in your App.xaml.  Firstly, merge in some of the usual MahApps dictionaries:

<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />

Then, where you specify the primary Material Design colour, setup the MahApps brushes, but instead of pulling in one of the MahApps accent dictionaries, configure them manually, to use the Material Design palette:

<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource Primary700}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush" Color="{StaticResource Primary500}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush2" Color="{StaticResource Primary400}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush3" Color="{StaticResource Primary300}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentColorBrush4" Color="{StaticResource Primary200}" options:Freeze="True" />
<SolidColorBrush x:Key="WindowTitleColorBrush" Color="{StaticResource Primary700}" options:Freeze="True" />
<SolidColorBrush x:Key="AccentSelectedColorBrush" Color="{StaticResource Primary500Foreground}" options:Freeze="True" />

For a complete example see this App.xaml.

Any controls added to your Window (or Dragablz TabablzControl) will now default to MahApps styles, but use the Material Design palette, leaving your application looking pretty good. Having got to this point myself, I couldn’t help but start playing around a bit further with some Material Design. I created a list box with a few cards and the result looked pretty promising:

MaterialDesignEarlyPrototype

It wasn’t long before I went even further and started styling a whole bunch of controls, and ended up with these:

MaterialDesignDemo2

I’ve packaged all these themes (and will continue to add to) on NuGet:

Install-Package MaterialDesignThemes

Where appropriate in your app you can include one or more of the contained resource dictionaries and use the Material Design style for a control in place of the MahApps. All of your other controls will still use the MahApps themes, meaning your application should always look great. A thorough-bred mash-up :)

To select the appropriate resource dictionary and style name the best thing to do is download the source/demo solution from GitHub and run the two projects in the solution:

  • MahMaterialDragablzMashUp
  • MaterialDesignColors.WpfExample

Or, take a look at this MainWindow.cs.

Hope that all helps you get a good looking application up and running quickly!

As an end note I must mention this great piece of styling in WinForms, which inspired me to create the Material Design theme for Dragablz in the first place.


Material Design DatePicker/Calendar Style for WPF

$
0
0

Howdi,

After a bit of toil I have the DatePicker and Calendar WPF control styles done for Material Design in XAML Toolkit. I hope you guys like it!

(Edit: TimePicker & Clock now also available, blogged here)
Material Design templates for DatePicker/Calendar primitive controls.
Material Design templates for DatePicker/Calendar primitive controls.

Please note that the behaviour is not quite identical to that which you might see on Android. These are templates for the existing WPF DatePicker and Calendar primitive controls, and thus, some of the behaviour around month/year selection is driven by the nature of those controls. There is no modal dialog, as I don’t want these templates to get confused with any requirement/API used to manage dialogs in WPF.

I must say that I believe that it is testament to the original design of WPF/XAML – which is now a mature technology – that I could slot these styles in pretty much seamlessly for a control whose code base is around 8 years old. Note that some extra code has gone in to the Material Design Toolkit, bit this is wrapped inside the new templates and thus if you consume these templates you need never concern yourself with it.

Getting started:

If you haven’t taken a look at Material Design in XAML Toolkit yet (or indeed Dragablz) here is a blog post to get started, or download the source from GitHub and fire up the demo projects:

  • MaterialDesignColors.WpfExample
  • MahMaterialDragablzMashUp

Thanks due:


Material Design Themed TimePicker and Clock Controls for WPF

$
0
0

I’ve managed to get the existing WPF controls; DatePicker & Calendar themed as part of Material Design in XAML Toolkit as described in this blog post.

But the fun part was cranking a couple of brand new controls to build the Material Design time picker experience:

  • TimePicker
  • Clock

These are sibling controls to the existing DatePicker and Calendar controls.  I wanted to keep the API experience similar so you can dive straight in without any kind of learning curve.  The Clock can be used in isolation, or use the DatePicker for an easy picker/popup/drop down behaviour.

Here’s a static glimpse at the picker:

Material Design Time Picker

And here’s a gif of the clock in action:

Material Design Clock Demo

There’s nothing complicated about using these, but you will need to get Material Design In XAML Toolkit referenced and set up in your app. Follow the initial tutorial, and head over to GitHub to download the source/examples project.


Open Sourcing a Logo

$
0
0

Open source doesn’t have to just apply to code.  I’ve been applying my XAML skills to Material Design In XAML Toolkit to help other developers quickly craft good looking user interfaces in WPF.  I’m pretty happy with the results, and in some of my own projects I’ve produced some striking applications using the toolkit.  Despite doing this, I readily admit I’m no designer.  For such a visually focused code library I really wanted a logo, but knew I could never do the task justice.

So I threw the task out to the community.

I created an issue on GitHub, tweeted a bit, posted on Reddit.  And waited.  Pretty much bang on 2 weeks later a result came back from a young guy called Sam, and I’m really happy with it:

Material Design In XAML Toolkit

Sam or “snalty” can be found on Twitter, and you can see some of his other designs on his blog.

In summary, a great bit of collaboration helping to push Material Design In XAML Toolkit further along.


Using MahApps Dialog Boxes in a MVVM Setup

$
0
0

Finally, after a couple of years of take, take, take; I’ve made a contribution to MahApps.  Working in a financial institution it’s not always easy to commit back to open source projects, so with a little bit of out-of-hours work I’ve solved a little problem I’ve seen a few people asking: “how do you use MahApps dialog boxes in an MVVM setup?”  And now my conscience is clear. ;)

Now You Can Launch a Dialog Box From a View Model.

There’s a couple of simple things you have to do:

1) Use an attached property in your Window to register your view model with the dialog sub-system.

Assuming your View’s DataContext is set to the view model from where you want to launch the dialog, add these attributes:


<Controls:MetroWindow 

        xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro" 
        Dialog:DialogParticipation.Register="{Binding}"
 >

2) Grab & Use DialogCoordinator to open dialogs.

You can instantiate DialogCoordinator directly, or, good citizens will probably want to inject in the interface IDialogCoordinator into their view model.  This will play nicely with TDD, and is agnostic to whatever DI framework you may be using.

Without a DI framework you could just do something like this:


new MainWindowViewModel(DialogCoordinator.Instance);

Opening up a dialog from your view model is now easy, using the IDialogCoordinator instance.  To most methods the first parameter named “context” will typically be your view model.  This is how the coordinator will match the view model to the window (with what was registered in step 1) and display the dialog.  If you have multiple windows open, the dialog will display on the correct window.  Show your dialog from inside your view model just like this:


_dialogCoordinator.ShowMessageAsync(this, "Message from VM", "MVVM based dialogs!")

If you want to see this in action and follow the code through open up the MahApps MetroDemo project (part of the MahApps source code), and launch from the “Dialogs” Menu:

Dialogs via MVVM in MahApps
Dialogs via MVVM in MahApps

This should make it into release 1.2.0.



Dealing with RX Exception, “Failed to start monitoring system clock changes”

$
0
0

With some pain we recently uncovered a risk in using Observable.Timer(...) in Reactive Extensions.

The system is a WPF real-time trading system, utilising RX heavily.  Some of our users access the system via Citrix, and it was these users who first started experiencing the issue.  Sporadically a thread pool callback would cause the system to crash with an unhandled exception.  The exception being thrown from inside RX:


System.InvalidOperationException: Failed to start monitoring system clock changes.
at System.Reactive.PlatformServices.PeriodicTimerSystemClockMonitor.NewTimer()
at System.Reactive.PlatformServices.PeriodicTimerSystemClockMonitor.TimeChanged()
at System.Reactive.Concurrency.ConcurrencyAbstractionLayerImpl.PeriodicTimer.Tick(Object state)
at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireQueuedTimerCompletion(Object state)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Being on Citrix I started hypothesising that this might be some kind of CPU load issue. Then we had another “normal” desktop user encounter the exception. Her application kept crashing and upon investigation I found another process on her 4 core box taking 25% CPU. Killing that process-which seemed to have gone rogue-suddenly cleared our application of the RX error. So again, it pointed to CPU bound slowness.

The actual RX source which throws the exception can be seen here, inside the NewTimer method.

If you use Observable.Timer(...) RX will internally create a new PeriodicTimerSystemClockMonitor instance and subscribe to its SystemClockChanged event. And this class creates a timer to raise the event. Everytime this timer calls back into TimeChanged a time threshold is checked. If the callback was too slow, a new timer will be generated within NewTimer. Again, the length of time it takes to create this timer is checked. If the SYNC_MAXDELTA milliseconds threshold is broken, another attempt is made. The loop allows for 100 attempts. If after this time the timer hasn’t been created within the allowed time threshold the offending InvalidOperationException is thrown.

At which point your application will die.

It took a few attempts of reading the code before I understood this; it is not immedietely easy to get this set-up in debug. I wanted to add some logging to give us an idea of how slow the timer recreation was. To achieve this I had implement a custom IPlatformEnlightenmentProvider (and set via: PlatformEnlightenmentProvider.Current = new CustomPlatformEnlightenmentProvider(); ), which unfortunately involved some reflection so I could instantiate existing classes internal to RX. But now I am able to get RX to use a ConfigurablePeriodicTimerSystemClockMonitor where I can get some logging going and experiemnt with the time thresholds.

The two classes are at the end of the article. The important thing is I can see when RX decides the callback is too slow and that a new timer is required. And then, when the exception is finally thrown inside NewTimer, I can see how slow the timer creation operation was:

if (n >= _syncMaxRetries)
{
    _logger.Warning("Failed to start monitoring system clock changes (Configurable Impl). diff={0}", diff);
    throw new InvalidOperationException(
        "Failed to start monitoring system clock changes (Configurable Impl).");
}

With all this in place I sat back and waited for the crash reports to come in. The first exception report looked like this:

Failed to start monitoring system clock changes (Configurable Impl). diff=489.0552

So in this case, a call which RX wants to happen within 10ms is taking nearly half a second. As of writing I have questions outstanding with our Citrix team, CPU usage/spikes/load, mem etc. I am also pondering other things: did a gen2 GC collect kick in? What other process are running? Do we also have a memory leak? etc etc. Perhaps clutching at a few straws :)

So what’s next?

I’ve got options, mainly two, but I don’t particularly like either:

  • Make the time check much more relaxed. But how relaxed? There is no line in the sand here…
  • Remove all usages of Observable.Timer. And stand guard over every developers’ check-ins for the application’s lifetime?!

Right now we are still contemplating our next step, collating information. I’ll try an update this post with our final approach. I will also try and solicit a response from the RX team for their opinion on this.

UPDATE: Solution From Microsoft

Kudos to the RX team at Microsft who very quickly came back with a possible solution. There’s a couple of gotchas, but its very workable. The suggestion is to “create a custom system clock monitor using SystemEvents.TimeChanged“.

So we rely on the Win32 event to notify RX of changes to the system clock, instead of the more complicated PeriodicTimerSystemClockMonitor which has all the time checks and constraints at the root of the problem we are seeing.

There’s a couple of small issues:

  • We will still have to use our custom IPlatformEnlightenmentProvider, which uses reflection to instantiate RX internal classes. This leaves us slightly vulnerable to future re-workings to the innards of RX. UPDATE: dealt with; see UPDATE 2 below.
  • The solution requires a message pump (which apparently is why RX doesn’t use this method by default). Luckily for us, being a WPF application, we have one.

So I’ve created a new class:

public class SystemEventsSystemClockMonitor : INotifySystemClockChanged
{
    private int _refCount;
    private EventHandler<SystemClockChangedEventArgs> _systemClockChanged;

    public event EventHandler<SystemClockChangedEventArgs> SystemClockChanged
    {
        add
        {
            AddRef();
            _systemClockChanged += value;
        }
        remove
        {
            RemoveRef();
            _systemClockChanged -= value;
        }
    }

    protected virtual void OnSystemClockChanged(SystemClockChangedEventArgs e)
    {
        var handler = _systemClockChanged;
        if (handler != null) handler(this, e);
    }

    private void AddRef()
    {
        if (Interlocked.Increment(ref _refCount) == 1)
        {
            SystemEvents.TimeChanged += SystemEventsOnTimeChanged;
        }
    }

    private void RemoveRef()
    {
        if (Interlocked.Decrement(ref _refCount) == 0)
        {
            SystemEvents.TimeChanged -= SystemEventsOnTimeChanged;
        }
    }

    private void SystemEventsOnTimeChanged(object sender, EventArgs eventArgs)
    {
        OnSystemClockChanged(new SystemClockChangedEventArgs());
    }
}

Then inside our CustomPlatformEnlightenmentProvider I can return it when asked inside GetService. I haven’t reflected that change in the implementation listed below so beware, understand what’s happening, and choose your INotifySystemClockChanged implementation wisely before using this in your system…

UPDATE 2: Slight improvement…

I’ve only just spotted that the RX factory method CurrentPlatformEnlightenmentProvider.GetService() is marked as virtual. So I can inherit from this, override and provide my custom class where applicable. This resolves any issue I had regarding reflection. Now the enlightenment provider is pretty simple:

public class CustomPlatformEnlightenmentProvider : CurrentPlatformEnlightenmentProvider
{
    public override T GetService<T>(object[] args)
    {
        var t = typeof(T);
        if (t == typeof (INotifySystemClockChanged))            
            return (T)(object)new SystemEventsSystemClockMonitor();            

        return base.GetService<T>(args);
    }
}

Happy days…

Customised RX classes, from before Microsoft proposed solution, which were used during investigation:

public class CustomPlatformEnlightenmentProvider : IPlatformEnlightenmentProvider
{
    private readonly ILogger _logger;
    private readonly bool _useCustomImplementations;

    public CustomPlatformEnlightenmentProvider(ILogger logger)
    {
        if (logger == null) throw new ArgumentNullException("logger");
        
        _logger = logger;

        _useCustomImplementations = Session.IsRunningRemotely || Debugger.IsAttached;
        if (_useCustomImplementations)
            _logger.Info("Platform enlightenment will run ConfigurablePeriodicTimerSystemClockMonitor.");
    }

    public T GetService<T>(params object[] args) where T : class
    {
        var t = typeof(T);
       
        if (t == typeof(IExceptionServices))
        {
            var type = Type.GetType("System.Reactive.PlatformServices.ExceptionServicesImpl, System.Reactive.PlatformServices", true);                
            return (T)Activator.CreateInstance(type);
        }

        if (t == typeof(IConcurrencyAbstractionLayer))
        {
            var type = Type.GetType("System.Reactive.Concurrency.ConcurrencyAbstractionLayerImpl, System.Reactive.PlatformServices", true);                
            return (T)Activator.CreateInstance(type);
        }

        if (t == typeof(IScheduler) && args != null)
        {
            switch ((string)args[0])
            {
                case "ThreadPool":
                    return (T)(object)ThreadPoolScheduler.Instance;
                case "TaskPool":
                    return (T)(object)TaskPoolScheduler.Default;
                case "NewThread":
                    return (T)(object)NewThreadScheduler.Default;
            }
        }

        if (t == typeof(INotifySystemClockChanged))
        {
            return (T) (_useCustomImplementations
                ? new ConfigurablePeriodicTimerSystemClockMonitor(
                    TimeSpan.FromSeconds(1), 
                    _logger,
                    syncMaxRetries: 100,
                    syncMaxDelta: 10)
                : (INotifySystemClockChanged) new PeriodicTimerSystemClockMonitor(TimeSpan.FromSeconds(1)));
        }


#if HAS_TPL46
        if (t == typeof(ITaskServices))
        {
            return (T)(object)new TaskServicesImpl();
        }
#endif

        if (t == Type.GetType("System.Reactive.Linq.IQueryServices, System.Reactive.Linq"))
        {
            //
            // We perform this Debugger.IsAttached check early rather than deferring
            // the decision to intercept query operator methods to the debugger
            // assembly that's dynamically discovered here. Also, it's a reasonable
            // expectation it'd be pretty hard to turn on interception dynamically
            // upon a debugger attach event, so we should make this check early.
            //
            // In the initial release of v2.0 (RTM), we won't have the corresponding
            // debugger assembly available yet, so the dynamic load would always
            // fail. We also don't want to take the price of (an attempt to) a dynamic
            // assembly load for the regular production case.
            //
            if (Debugger.IsAttached)
            {
#if NETCF35
                var name = "System.Reactive.Linq.QueryDebugger, System.Reactive.Debugger";
#else
#if (CRIPPLED_REFLECTION && HAS_WINRT)
                var ifType = t.GetTypeInfo();
#else
                var ifType = t;
#endif
                var asm = new AssemblyName(ifType.Assembly.FullName);
                asm.Name = "System.Reactive.Debugger";
                var name = "System.Reactive.Linq.QueryDebugger, " + asm.FullName;
#endif
                var dbg = Type.GetType(name, false);
                if (dbg != null)
                    return (T)(object)Activator.CreateInstance(dbg);
            }
        }            

        return null;
    }
}

public class ConfigurablePeriodicTimerSystemClockMonitor : INotifySystemClockChanged
{
    private readonly TimeSpan _period;
    private readonly ILogger _logger;
    private readonly SerialDisposable _timer;

    private DateTimeOffset _lastTime;
    private EventHandler<SystemClockChangedEventArgs> _systemClockChanged;

    private readonly int _syncMaxRetries = 100;
    private readonly double _syncMaxDelta = 10;
    private readonly int _maxError = 100;

    /// <summary>
    /// Creates a new monitor for system clock changes with the specified polling frequency.
    /// </summary>
    /// <param name="period">Polling frequency for system clock changes.</param>
    /// <param name="logger"></param>
    /// <param name="syncMaxRetries"></param>
    /// <param name="syncMaxDelta"></param>
    /// <param name="maxError"></param>
    public ConfigurablePeriodicTimerSystemClockMonitor(TimeSpan period, ILogger logger, int syncMaxRetries = 100, int syncMaxDelta = 10, int maxError = 100)
    {
        if (logger == null) throw new ArgumentNullException("logger");

        _period = period;
        _logger = logger;
        _syncMaxRetries = syncMaxRetries;
        _syncMaxDelta = syncMaxDelta;
        _maxError = maxError;

        _timer = new SerialDisposable();
    }

    /// <summary>
    /// Event that gets raised when a system clock change is detected.
    /// </summary>
    public event EventHandler<SystemClockChangedEventArgs> SystemClockChanged
    {
        add
        {
            NewTimer();

            _systemClockChanged += value;
        }

        remove
        {
            _systemClockChanged -= value;

            _timer.Disposable = Disposable.Empty;
        }
    }

    private void NewTimer()
    {
        _timer.Disposable = Disposable.Empty;

        double diff;
        var n = 0;
        do
        {
            _lastTime = SystemClock.UtcNow;
            _timer.Disposable = PlatformEnlightenmentProvider.Current.GetService<IConcurrencyAbstractionLayer>().StartPeriodicTimer(TimeChanged, _period);
            diff = Math.Abs((SystemClock.UtcNow - _lastTime).TotalMilliseconds);
        } while (diff > _syncMaxDelta && ++n < _syncMaxRetries);

        _logger.Info("Took {0} attempts to start new timer.", n);

        if (n >= _syncMaxRetries)
        {
            _logger.Warning("Failed to start monitoring system clock changes (Configurable Impl). diff={0}", diff);
            throw new InvalidOperationException(
                "Failed to start monitoring system clock changes (Configurable Impl).");
        }
    }

    private void TimeChanged()
    {
        var now = SystemClock.UtcNow;
        var diff = now - (_lastTime + _period);
        if (Math.Abs(diff.TotalMilliseconds) >= _maxError)
        {
            var scc = _systemClockChanged;
            if (scc != null)
                scc(this, new SystemClockChangedEventArgs(_lastTime + _period, now));

            _logger.Warning("Clock Monitor exceeded max error, initiating new timer. Vars: now={0}, _lastTime={1}, diff={2}", now.ToString("O"), _lastTime.ToString("O"), diff);

            NewTimer();
        }
        else
        {
            _lastTime = SystemClock.UtcNow;
        }
    }
}

 


React.js and Material Design Lite

$
0
0

I’m a bit of a React.js fan lately, and with the arrival of Google’s Material Design Lite, I decided to combine them for a little project I’m throwing together.  Turns out to be pretty easy.  To simplify the Getting Started, you need to include a .css and .js file in your page:

<link rel="stylesheet" href="https://storage.googleapis.com/code.getmdl.io/1.0.0/material.grey-blue.min.css" />
<script src="https://storage.googleapis.com/code.getmdl.io/1.0.0/material.min.js"></script>

…and then show a Material Design button using the following class names:

<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect">
  Button
</button>

The small gotcha for using templating techniques for dynamic pages such as with React.js is that for buttons, and other items, dynamically added you need to call a bit of script to upgrade the button:

//where button is your DOM element
componentHandler.upgradeElement(button, 'MaterialButton');

But when we come to create our React class, that’s easily handled in componentDidMount, leaving my Material Design Lite button class looking like this:

var MdlButton = React.createClass({
	handleClick: function() {
		this.props.onClick();	
	},
	render: function() {
		return (
			<button ref="btn" className="mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect"
					onClick={this.handleClick}>
				{this.props.content}
			</button>
		);
	},
	componentDidMount: function() {
		componentHandler.upgradeElement(React.findDOMNode(this.refs.btn), 'MaterialButton');		
	} 
});

One small thing to note is the second arg to upgradeElement where we are passing in ‘MaterialButton’. As of now the docs aren’t overly clear on this, but it’s the name of the Javascript function object defined in the source. So, if we want to create a check box React class we can dig in to the Material Design Light source code in GitHub, and confirm that we’d pass ‘MaterialCheckbox’ into upgradeElement.

No doubt the community will provide a full library for this in time, but it doesn’t take much to combine these two libraries.


Version 1.0 of Material Design In XAML has arrived!

$
0
0

Well, this project kinda came out of nowhere, but has proven to be pretty popular and I’ve really enjoyed getting it to this state: version 1.0!   It’s officially a non-alpha, non-beta, totally live thing!!

I’ve cranked up my contributions over the last month to push it over the line for its for first official release, recently adding runtime palette switching via the PaletteHelper/Swatch API, a new ColorZone control to help you design your layouts, and more granular control of ripples and shadows.  A few styles and animations have also been tweaked to really improve the look and feel.

To go with version one I’ve completely re-worked the demo app, as illustrated in the video.  It’s really worth checking, it might just give you some inspiration for your WPF apps!

And if you haven’t seen I recently launched a new home page for the project: materialdesigninxaml.net, which includes a Get Started section.

There’s still plenty more to come for both Material Design In XAML and Dragablz but I will be treating myself to a little break for a week or two!


Bending the WPF ProgressBar

$
0
0

There’s plenty progress loop controls around for WPF, but for Material Design In XAML Toolkit I really wanted to stick to “themeing” existing framework controls where-ever possible. Here’s examples of what were trying to achieve from Google’s own documentation, if you have an Android phone you’ll no doubt have seen these in action:

Before I tackled the style I spent a few weeks bouncing ideas around in my head.  To create the circular effect we’d have to dust off the trigonometry but I really wasn’t sure if I cold pull it all off inside a WPF Style, without creating a new control, or at least inheriting (yuck) from ProgressBar.  ProgressBar says it all.  It wasn’t really designed to go where I wanted it to go and whilst weighing things up I reflected into the ProgressBar.cs source:


//----------------------------------------------------------------------------
// File: ProgressBar.cs
//
// Description:
// Implementation of ProgressBar control.
//
// History:
// 06/28/2004 - t-sergin - Created
//
// Copyright (C) 2004 by Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------

Okaaaayyy…so using the ever flexible WPF we are still taking something from 2004 and trying to theme it using 2015 design trends.  Should be fun!  There are a few TemplatePart’s which the code it expects – to draw a standard bar – but fortunately the control is also gracious enough to operate without them.

To create the looping progress ring thingy a simple arc path should do the job:

<Path>
  <Path.Data>
    <PathGeometry>
      <PathFigure StartPoint="?">
        <ArcSegment Size="?" IsLargeArc="?" Point="?" SweepDirection="Clockwise" />
      </PathFigure>
    </PathGeometry>
  </Path.Data>
</Path> 

But you’ll see from the attributes with a ? we’ve got 4 values we’ve got to complete:

  • PathFigure.StartPoint: pretty simple, start the arc at the top, on the middle of the X axis
  • ArcSegment.Size: easy again, this is the radius, so half the size of the control
  • ArcSegment.IsLargeArc: to draw anything over 180deg, this needs to be set to true. We’ll need a multiple values to figure out if we are over half way through progress: ProgressBar.Minumum, .Maximum, .Value
  • ArcSegment.Point: This is where from the StartPoint we need to draw our arc around to. Again we’ll need ProgressBar.Minumum, .Maximum, .Value, and with the wonders of trigonometry we can figure this out.

No worries though, we can wrap all of these little calculations in a bunch of IValueConverter and IMultiValueConverter implementations.  In reality then, bending a straight progress bar into a circle is pretty simple.  The PathFigure – now, peppered with a bunch of value converters – looks a bit like this:


<PathFigure StartPoint="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource StartPointConverter}, Mode=OneWay}">
<ArcSegment Size="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource ArcSizeConverter}, Mode=OneWay}" SweepDirection="Clockwise">
<ArcSegment.IsLargeArc>
<MultiBinding Converter="{StaticResource LargeArcConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
<Binding ElementName="FullyIndeterminateGridScaleTransform" Path="ScaleX" />
</MultiBinding>
</ArcSegment.IsLargeArc>
<ArcSegment.Point>
<MultiBinding Converter="{StaticResource ArcEndPointConverter}">
<Binding ElementName="PathGrid" Path="ActualWidth" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
<Binding ElementName="FullyIndeterminateGridScaleTransform" Path="ScaleX" />
</MultiBinding>
</ArcSegment.Point>
</ArcSegment>
</PathFigure>

(I don’t think WordPress wants to format that…)

We’re not done there though.  Material Design has extra animation flourishes to provide the extra pzazz.  If you look at the determinate loop in the video above, you’ll see that the whole ring is rotating in addition to drawing out the arc representing completion.  Something, a bit like this:

ProgressRingDoubleRotate

By applying a RotateTransform to the Path itself, and using yet another converter to calculate the rotation according to the percent of completion we can pretty close to the Google effect.


<Path.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="RotateTransform" CenterX="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource RotateTransformCentreConverter}, Mode=OneWay}" CenterY="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource RotateTransformCentreConverter}, Mode=OneWay}">
<RotateTransform.Angle>
<MultiBinding Converter="{StaticResource RotateTransformConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
</MultiBinding>
</RotateTransform.Angle>
</RotateTransform>
</TransformGroup>
</Path.RenderTransform>

I’ve actually built further animation storyboards on top of this to try and get close to the indeterminate effect.  It’s not quite perfect yet, but close enough for what I released in version 1.0 of Material Design In XAML Toolkit.  Here’s a gif of how things were looking in that release:

Progress Loops

And, in keeping with my original challenge of staying close to the original .Net Framework controls, usage is pretty straight forward:


<ProgressBar Style="{StaticResource MaterialDesignCicularProgressBar}" Value="50" />

To see it in action run up the demo project which is part of the main source.

The actual final style can be found here:

https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/blob/master/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.ProgressBar.xaml

And – as there are a whole bunch of converters – they warrant their own namespace here:

https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/tree/master/MaterialDesignThemes.Wpf/Converters/CircularProgressBar


WPF Dialog Boxes In Material Design In XAML Toolkit

$
0
0

(Note this article refers to a pre-release version, which can be found on nuget provided pre-release versions are included in your search.)

Message boxes.  Ever a source of frustration in WPF.  MahApps has some nice dialog boxes to which I recently helped out with an MVVM API, but Material Design In XAML Toolkit can run with or without MahApps so I wanted a custom implementation which would meet these goals:

  • Look similar to the dialogs we see on Android phones
  • Have an API which is useable from XAML, code-behind, and MVVM
  • Provide full flexibility on the content of the dialog.

All software is evolution and after a reasonable attempt of doing something similar for a client – which ended up with a bit of a code-smell around callbacks from the API – I’ve come up some composable pieces which I hope are flexible, easy to use, and – most importantly – provide an attractive GUI :-)

The cornerstone is the DialogHost control.  It’s a content control, meaning the underlying content over which the popup dialog will be displayed can be targeted; to a specific area of your app, or the entire Window content.


<md:DialogHost>
    <md:DialogHost.DialogContent>
        <dialogContent />
    </md:DialogHost.DialogContent>
    <mainContent />
</md:DialogHost>

When the dialog is open, the underlying content will be dimmed and disabled.

Material Design Dialog

DialogHost.DialogContent (associated with DialogHost.DialogContentTemplate) is your typical XAML content object property for setting the content of your dialog.  You can infer from this that you can use MVVM to bind content, but there are multiple ways of populating the content, showing the dialog, closing the dialog, and processing responses, so here’s a list of all the strategies for using the dialog (after the gif):

Material Design Dialog

Open Dialog Strategies

DialogHost.OpenDialogCommand

<Button Command="{x:Static md:DialogHost.OpenDialogCommand}" />

RoutedCommand typically used from a button where optional content can be provided via the CommandParameter.

DialogHost.IsOpen

<md:DialogHost IsOpen="True" />

Dependency property, to be triggered from XAML, set from code-behind or via a binding.  Content must be set in DialogHost.DialogContent.

DialogHost.Show

DialogHost.Show(viewOrModel);

Async/await based static API which can be used purely in code (for example from in a view model).  Content can be passed directly to the dialog.

Close Dialog Strategies

DialogHost.CloseDialogCommand

<Button Command="{x:Static md:DialogHost.CloseDialogCommand}" />

RoutedCommand, typically used on buttons inside the dialog, where the command parameter will be passed along to the dialog response.

DialogHost.IsOpen

<md:DialogHost IsOpen="False" />

Dependency property, to be triggered from XAML, set from code-behind or via a binding.

HANDLE CLOSE STRATEGIES

The DialogClosingEventHandler delegate is key.  It provides the parameter provided to DialogHost.CloseDialogCommand, and allows the pending close to be cancelled.

The following mechanisms allow handling of this event, via code-behind, MVVM practices, or just from the code API:

DialogHost.DialogClosing

<md:DialogHost DialogClosing="DialogHost_OnDialogClosing" />

Bubbling RoutedEvent, which could be used in code-behind.

DialogHost.DialogClosingAttached

<Button Command="{x:Static wpf:DialogHost.OpenDialogCommand}" md:DialogHost.DialogClosingAttached="DialogHost_OnDialogClosing" />

Attached property, which accepts a DialogClosingEventHandler which makes it easy to subscribe to the closing event in a more localized area of XAML.

DialogClosing.DialogClosingCallback

<md:DialogHost DialogClosingCallback="{Binding DialogClosingHandler}" />

Standard dependency property which enables the a DialogClosingEventHandler implementation to be bound in, typically from a view model.

DialogHost.Show

var result = await DialogHost.Show(viewOrModel, ClosingEventHandler);

The async response from this method returns the parameter provided when DialogHost.CloseDialogCommand was executed.  As part of the Show() signature a DialogClosingEventHandler delegate can be provided to intercept the on-closing event, just prior to the close.

More Examples

More complete usage examples can be found in MainDemo.Wpf which is part of the Toolkit solution, primarily in MainDemo.Wpf/Dialogs.xaml.


Resolving A Dead Lock Is Your Number 1 Priority.

$
0
0

If your app deadlocks during development you might not want the added distraction. Surely you’ve got some feature which you need to get finished off in a hurry that your boss is pressurising you for. Maybe the screen deadlocking is something your colleague is working on, so you can just let them know and get back to the job at hand.

No.

You now know there’s a deadlock. Some deadlocks manifest readily. But others are a rare breed that only happen under rare circumstances, and perhaps even rarer on your CPU compared to those that you will deploy to. If you ignore this deadlock, it’s on your head.

The reality is: you just got lucky. Your team got lucky. You can resolve this problem here and now, without it escaping into the wild.

Stop what you are doing, forget what your boss wants you to do, or whatever task you think you need to do, and investigate the deadlock and knock the problem on the head.

Often I have heard developers say something like, “yeah, it deadlocks there sometimes”. Or worse, “yeah that’s the so-and-so’s code”. But they don’t stop to investigate. They just assume it’s someone-else’s responsibility

It can take time to resolve a deadlock. Sometimes they are pretty easy, but sometimes they can be complex beasts which take time to understand. Threaded code is more often tricky than not, and problems can be oh-so-subtle. But don’t shun it. Be a hero. Solve it.

Whenever I get a deadlock I immediately cease what I am doing. I pause Visual Studio (being my typical dev tool of choice) and put everything to one side. I won’t close the debug session until I am done. Is it half-five and I’ve got to pick the kids up? No problem. Visual Studio occasionally crashes during debug sessions but I have never had a problem when it is left paused. I’ll just leave it overnight, and come back to it with a fresh head in the morning.

I get the Call Stack up, get the Threads window open and sit there – sometimes just staring for long periods – and try and work through what’s happening. Often in large systems I’ll be working through vast swathes of code I’ve never seen before. There might be multiple context switches, some red-herrings, some code that is down-right ugly. Compiled libraries that you have to break open Refelector/dotPeek or browse Git source to understand. It can be hard, and it can take time: I’ve sat there for hours at a time trying to get things straight in my head, scratching notes on paper, perhaps even firing up another instance of Visual Studio to run through scenarios.

Maybe I’ll take a break, get a drink, some fresh air; but I won’t leave that debug session until I understand what’s causing the deadlock and how I’m going to go about fixing it.


Material Design In XAML Toolkit: version 1.2

$
0
0

I’m happy to say that Material Design In XAML Toolkit version 1.2 has rolled, bringing yet more polish and features that are hopefully going to help people bring their desktop applications to life.

Links:

Key features of note:

ComboBox styling

This great PR as brought the combo style bang up to date with Google’s spec, and it looks great.

NewCombo

TimePicker goes 24 hour

24hrClock

<materialDesign:Clock Is24Hours="True" DisplayAutomation="Cycle" />

Thanks to pauloquicoli for helping out here.

Additional Slider theme

9c2a7e3a-8988-11e5-86ac-cef4159ba661

<Slider 
    Minimum="0" 
    Maximum="10" 
    Style="{DynamicResource MaterialDesignDiscreteSlider}"  />

DialogHost improvements

dialogs

The DialogHost control provides Material Designed themed popups and also provides a comprehensive API to deal with popup dialogs, which have traditionally been a pain point for WPF developers. This release polishes some of the API for both MVVM and code-behind scenarios.  Some great community testing has helped round this off, and also some code comes from here.

Read more about DialogHost popups

 

Thanks to all contributors for helping to not only move this project forward, but also helping drive its success; it’s really exciting how much traction this library has gained since I started it.

Coming Next

For 1.3 I’ve already started working on a “Multiple Floating Action Button” which is quite common on Android, and there will be a few smaller tweaks.  Also, as ever, I’ll be plugging away at Dragablz as I try and approach a version 1.0.  UWP stuff?  Still a pet project at the moment :)



ViewModelBase: go away.

$
0
0

So yeah, this isn’t directed at people doing cool Flux models with React.js, no, this is for those of use still plying the MVVM pattern with rich clients using XAML.

I hate “ViewModelBase”. “NotifyPropertyChangedBase”.  Whatever.  The basic thinking is, yeah, we do this a lot, let’s make a base class with all our common view model stuff.  Whatever.  I hate it.  Inheritance, is in most part, a trouble-making aspect of object orientation which for many cases can be avoided.

Composition makes your objects much more malleable, and this applies as much to your view model as elsewhere.

So yeah, it might cost a line or two extra, but we have CallerMemberName, and with C# 6.0 the amount of code required to implement  OnPropertyChanged is minimal:

private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

I get that property change methods can get tedious.  I’ve seen this code about a lot: the “Set” method which checks equality and makes the change.

But even so, enforcing an inheritance chain for this?  Pah.  Not interested.  I’ve see so many large enterprise systems creaking at their foundations due to cumbersome inheritance models that I just wont bother.  If you really want to encapsulate the check ‘n’ raise code, how about using an extension instead?  Something like this:

public static class NotifyPropertyChangedExtension
{
    public static void MutateVerbose<TField>(this INotifyPropertyChanged instance, ref TField field, TField newValue, Action<PropertyChangedEventArgs> raise, [CallerMemberName] string propertyName = null)
    {            
        if (EqualityComparer<TField>.Default.Equals(field, newValue)) return;
        field = newValue;
        raise?.Invoke(new PropertyChangedEventArgs(propertyName));            
    }
}

This means in your view model, yeah – you’ll have to declare the event, but I’ll take that one line over inheritance any day, and the final result is still pretty succinct:

public sealed class ViewModel : INotifyPropertyChanged
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            this.MutateVerbose(ref _name, value, args => PropertyChanged?.Invoke(this, args));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Generate a C# Enum with Rosyln

$
0
0

I’m currently working on an Icon Pack for my Material Design library and need to generate an enum containing a list of all the icons.  Before you delve into this code you should know that the same result could no doubt be achieved using simple string manipulation in a lot less time.  But I took this as an opportunity to learn a little about Roslyn, so if that’s what you’re after then read on.

I set about creating a code template for the enum with the intention of using Roslyn to clear the dummy enum values out and re-populate the enum with a new list.  Sourcing the list of values is the easy part and not discussed here.

To begin with, this is my starting code template:

namespace MaterialDesignThemes.Wpf
{
    /// ******************************************
    /// This code is auto generated. Do not amend.
    /// ******************************************

    /// <summary>
    /// List of available icons for use with <see cref="Icon"/>.
    /// </summary>
    /// <remarks>
    /// All icons sourced from Material Design Icons Font - <see cref="https://materialdesignicons.com/"> - in accordance of 
    /// <see cref="https://github.com/Templarian/MaterialDesign/blob/master/license.txt"/>.
    /// </remarks>;
    public enum IconType
    {
        AutoGeneratedDoNotAmend
    }
}

First lesson.  If you want to do something similar, install the .Net Compiler Platform SDK.  Stupidly I didn’t do this until I had the code 75% complete.  The solution below looks pretty simple but as is oft the way, figuring it out was the hard part.  The Syntax Visualizer Visual Studio add-in included in the SDK would have got me there a lot quicker.

If I had of used the Visualizer in VS 2015 earlier (View > Other Windows > Syntax Visualizer), upon highlighting my above code template I would have seen this, which gives you a pretty good idea of what we’re working with:

SyntaxVisualizer

Second lesson.  The nuget package you are probably after is (took me a bit of digging to get the right one):

Microsoft.CodeAnalysis.CSharp.Workspaces

Also, I found ReSharper’s Hierarchy tool pretty useful to start understanding the class relationships; soon realising that we’re going to be spending a lot of time working with SyntaxNode objects and derivations thereof:

SyntaxNodeHierarchy

One of the first things to learn about Roslyn SyntaxNode objects is that they are immutable.  If you make a change then you’ll get a new one.  Obviously what we want to do is remove our AutoGeneratedDoNotAmend enum value (EnumMemberDeclarationSyntax) from the owning enum (EnumDeclarationSyntax) and replace it with a bunch of new members.  Meaning we’ll end up with a new enum/EnumDeclarationSyntax, in turn meaning we need to swap it out in the parent (NamespaceDeclaration) which again give us a new namespace, so we’ll have to swap that in the root’s children giving us a new root.  Effectively we start at the bottom and replace/renew everything walking up the ancestry of the tree.

Maybe there’s a better way, but this is my first crack at Roslyn and is very much a learning experience.

My first cut of the code (done prior to me installing the Visualizer/SDK, and using some pretend enum values) turned out like this:

private void UpdateEnum(string sourceFile)
{
    var sourceText = SourceText.From(new FileStream(sourceFile, FileMode.Open));
    var syntaxTree = CSharpSyntaxTree.ParseText(sourceText);

    var rootNode = syntaxTree.GetRoot();
    var namespaceDeclarationNode = rootNode.ChildNodes().Single();
    var enumDeclarationSyntaxNode = namespaceDeclarationNode.ChildNodes().OfType&amp;amp;amp;amp;amp;lt;EnumDeclarationSyntax&amp;amp;amp;amp;amp;gt;().Single();            

    var emptyEnumDeclarationSyntaxNode = enumDeclarationSyntaxNode.RemoveNodes(enumDeclarationSyntaxNode.ChildNodes().OfType&amp;amp;amp;amp;amp;lt;EnumMemberDeclarationSyntax&amp;amp;amp;amp;amp;gt;(), SyntaxRemoveOptions.KeepDirectives);
    var generatedEnumDeclarationSyntax = emptyEnumDeclarationSyntaxNode.AddMembers(
        SyntaxFactory.EnumMemberDeclaration("Aston"),
        SyntaxFactory.EnumMemberDeclaration("Villa"));

    var generatedNamespaceDeclarationSyntaxNode = namespaceDeclarationNode.ReplaceNode(enumDeclarationSyntaxNode, generatedEnumDeclarationSyntax);
    var generatedRootNode = rootNode.ReplaceNode(namespaceDeclarationNode, generatedNamespaceDeclarationSyntaxNode);

    Console.WriteLine(generatedRootNode.ToFullString());
}

The end result was pretty good, we retain the namespace declaration, comments, but we’ve lost something in the formatting:

namespace MaterialDesignThemes.Wpf
{
    /// ******************************************
    /// This code is auto generated. Do not amend.
    /// ******************************************

    /// <summary>
    /// List of available icons for use with <see cref="Icon"/>.
    /// </summary>
    /// <remarks>
    /// All icons sourced from Material Design Icons Font - <see cref="https://materialdesignicons.com/"> - in accordance of
    /// <see cref="https://github.com/Templarian/MaterialDesign/blob/master/license.txt"/>.
    /// </remarks>
    public enum IconType
    {
Aston,Villa    }
}

More digging and I learn how to create my enum member with “trivia” consisting of leading white space:

var leadingTriviaList = SyntaxTriviaList.Create(SyntaxFactory.Whitespace("        "));
var generatedEnumDeclarationSyntax = emptyEnumDeclarationSyntaxNode.AddMembers(
    SyntaxFactory.EnumMemberDeclaration(SyntaxFactory.Identifier(leadingTriviaList, "Aston", SyntaxTriviaList.Empty)),
    SyntaxFactory.EnumMemberDeclaration(SyntaxFactory.Identifier(leadingTriviaList, "Villa", SyntaxTriviaList.Empty)));               

Current result:

public enum IconType
{
    Aston,        Villa    }

This is good, but I now realised I needed to add a line feed, but to do this I needed the sibling “CommaToken” node to have the correct trailing trivia. I discovered this by tweaking my initial template to include two enum values and taking a look at the Syntax Visualizer:

SyntaxEnumComma

Yikes. This is starting to give me a headache.

Remembering that these toys we are playing with are immutable, I concocted a new method to pull all the comma tokens, and replace with new comma tokens with trailing line feed trivia:

. . .
generatedEnumDeclarationSyntax = AddLineFeedsToCommas(generatedEnumDeclarationSyntax);
. . .

private static EnumDeclarationSyntax AddLineFeedsToCommas(EnumDeclarationSyntax enumDeclarationSyntax)
{
    var none = new SyntaxToken();
    var trailingTriviaList = SyntaxTriviaList.Create(SyntaxFactory.ElasticCarriageReturnLineFeed);

    Func<EnumDeclarationSyntax, SyntaxToken> next = enumSyntax => enumSyntax.ChildNodesAndTokens()
        .Where(nodeOrToken => nodeOrToken.IsToken)
        .Select(nodeOrToken => nodeOrToken.AsToken())
        .FirstOrDefault(
            token =>
                token.Value.Equals(",") &&
                (!token.HasTrailingTrivia || !token.TrailingTrivia.Any(SyntaxKind.EndOfLineTrivia)));

    SyntaxToken current;
    while ((current = next(enumDeclarationSyntax)) != none)
    {
        enumDeclarationSyntax = enumDeclarationSyntax.ReplaceToken(current,
            SyntaxFactory.Identifier(SyntaxTriviaList.Empty, ",", trailingTriviaList)
            );
    }

    return enumDeclarationSyntax;
}

Our result now is looking much better:

namespace MaterialDesignThemes.Wpf
{
    /// ******************************************
    /// This code is auto generated. Do not amend.
    /// ******************************************

    /// <summary>;
    /// List of available icons for use with <see cref="Icon">.
    /// </summary>
    /// <remarks>
    /// All icons sourced from Material Design Icons Font - <see cref="https://materialdesignicons.com/"/> - in accordance of
    /// <see cref="https://github.com/Templarian/MaterialDesign/blob/master/license.txt"/>.
    /// </remarks>
    public enum IconType
    {
        Aston,
        Villa    }
}

There’s just that last curly bracket which needs knocking down a line, but I guess I’ll just have to get back to that…


Icon Pack – Material Design In XAML 1.4

$
0
0

New for release 1.4 of Material Design In XAML Toolkit is a full icon pack.  Icon design is a skill itself and finding or creating good icons when designing an application can be a time consuming task.   To help  in this regard I am pleased to announce that the entire Material Design Icons collection is now included in the library.

MaterialDesignIcons.png

It’s a  great collection, containing over 1,400 icons, including many of  the standard icons we see on Android phones and many more additional icons added by its own community.   It’s worthwhile heading over to the website to get an overview of the icons, and there’s a search feature to help  you track down the icon you’re after.

Using the icons in your WPF application is easy.  Assuming you’ve already installed Material Design In XAML Toolkit, the XAML is as simple as:


<materialDesign:PackIcon Kind="ShareVariant" />

To give you: share-variant-16.png

The icons are SVG based, so scale nicely:

<materialDesign:PackIcon Kind="ThumbUp" Height="24" Width="24" />
<materialDesign:PackIcon Kind="ThumbUp" Height="36" Width="36" />
<materialDesign:PackIcon Kind="ThumbUp" Height="48" Width="48" />

thumb-up-24.png  thumb-up-36.png  thumb-up-48.png

You can see the entire icon collection in the main demo application:

IconPack.png

MahApps

Furthermore, the base class for the icon has been added to ControlzEx (credit to @punker76 for this idea), so in the future you may well see MahApps use the same API for Modern Design Language icons, giving WPF developers a common, simple icon XAML syntax:

<materialDesign:PackIcon Kind="SomeMaterialIcon" />
<mahApps:PackIcon Kind="SomeModernIcon" />

Release Details

Various other fixes, enhancements, performance improvements have recently gone into the library.  Versions 1.3.1, 1.3.2, and now 1.4.0 contain some welcome community contributions.  To see details of all changes hit the Releases GitHub page.


Material Design In XAML – 1.5

$
0
0

It’s a big new release for MD in XAML Toolkit! This release focuses on a new transitions API (when I say API, I mean fully usable from XAML), which takes the pain out of WPF storyboard-ing, making animations on individual elements, and between whole “pages” easy.

Release page.

To showcase what can be done I’ve created an entirely new demo app. What’s great is that I was able to build version 1.0 of the demo app in less than a day. All the animations are “out of the box”; straight from Material Design In XAML Toolkit, with zero fiddling with WPF storyboards or animations (but yes, the extensibility is still there!)

It looks a bit like this:

main.gif

You can get your hands on the new demo at it’s new GitHub page.

On top of that there is also a small demo in the main Material Design In XAML Toolkit demo project.

To understand usage of the new transitions API, take a look at both demos and check out the wiki page.

I say this every release, but it’s always true, there have also been some great additions and fixes from the community (which is really growing nicely).  Full release details are here.

I guess with any software library it takes a while to gain traction, but this library is now just over a year old, seems to have plenty of users and I’m seeing some nice looking UIs appear.  With 1.5 I’m hoping for some nice animation flourishes!

Happy UXing!

James

P.S. n00b to Material Design In XAML Toolkit?  Check out the Getting Started guide.

 


SemVer, MVP and finally, Material Design In XAML 2.0.

$
0
0

This release of Material Design In XAML has taken way longer than I hoped, and contains less than I had hoped, so I apologise for that.  I’m trying to follow SemVer, and a couple of breaking changes meant it was time to tick over to v2.  Up until now I’ve been keeping to small, regular releases, but knowing it was time to go to v2 I thought I’d go for a big, showcase release.  I failed.  In assigned issues to the milestone I bit off way more than I could chew, even with the help of my (awesome) contributors.

md-chips.png

I read a tweet a while back saying someone couldn’t trust an open source library as the versions had ticked up high; indicating API instability.  There’s no doubt some truth in that, but in holding back a release (maybe so you can batch together several API changes) you start encountering the pitfalls of those longer release cycles.  Remember, that most open source projects are side projects, and time can be in short supply.  To be honest, I became a bit disheartened because I started realising I couldn’t deliver everything I wanted in this release.

md-list-toggle.png

So, I decided to draw a line under what we’ve got, roll the release, and get back to the shorter release cycles.  I try hard to keep the public surface of the library stable, but in the future, when it’s time to move, I will move more quickly.  Even if it means ticking over SemVer more regularly.

MVP.jpg

The good news.  The release is still pretty awesome.  New Chip controls, new Toggle styled listboxes, and many other enhancements.  Also, I’ve been privileged to receive a Microsoft MVP award for Windows Development.  I’m pretty stoked about this, it’s definitely nice to get some recognition for the open source journey I’ve been on over the last few years.  A big thanks is owed to everyone that’s helped this library grow and become something referenced in a lot of WPF systems.

Version 2.0 is now up on nuget.  Download and enjoy!

The full release notes are on GitHub.


Viewing all 24 articles
Browse latest View live