A couple of Resharper Live Templates for Caliburn.Micro items.

These are a couple of Live Templates for Resharper that help with some of the property declarations to work with Caliburn.Micro (the WPF framework originally from Rob Eisenberg).

I just use the naming convention CM followed by the purpose of the template. Both are available as a zip file via the link at the end of this article.

CMButton:

        private bool _can$BUTTONNAME$;
        public bool Can$BUTTONNAME$
        {
            get { return _can$BUTTONNAME$; }
            set
            {
                if (_can$BUTTONNAME$ == value) return;
                _can$BUTTONNAME$ = value;
                NotifyOfPropertyChange(() => Can$BUTTONNAME$);
            }
        }
        public void $BUTTONNAME$()
        {
           throw new NotImplementedException();
 
        }

This creates both the Button action method and the Can<method name> flag which is automatically used by Caliburn.Micro to enable/disable the button.

Only one item to complete ($BUTTONNAME$) when you use the template. Usually typing c m b is enough to get the template selected.

If you enter the button name as Edit the resulting code is:

        private bool _canEdit;
 
        public bool CanEdit
        {
            get { return _canEdit; }
            set
            {
                if (_canEdit == value) return;
                _canEdit = value;
                NotifyOfPropertyChange(() => CanEdit);
            }
        }
 
        public void Edit()
        {
            throw new NotImplementedException();
 
        }

Saves a whole load of typing! In the XAML you use x:Name = “Edit” in the <Button /> declaration and Caliburn.Micro does the rest.

 

CMProperty

        private $TYPE$ _$BACKINGFIELD$;
 
        public $TYPE$ $PROPERTYNAME$
        {
            get { return _$BACKINGFIELD$; }
            set
            {
                _$BACKINGFIELD$ = value;
                NotifyOfPropertyChange(()=>$PROPERTYNAME$ );
            }
        }

Slightly more complex than CMButton. This has three values: $TYPE$, $BACKINGFIELD$ and $PROPERTYNAME$. However, only $TYPE$ and $BACKINGFIELD$ need to be input – $PROPERTYNAME$ is generated from $BACKINGFIELD$.

$TYPE$ is the first item asked for – a drop down list of available Types will appear.

As $BACKINGFIELD$ is private start the name in lower case. The $PROPERTYNAME$ is produced with an Upper case first letter. So if you type firstName the property name will be FirstName.

       private String _firstName;
 
       public String FirstName
       {
           get { return _firstName; }
           set
           {
               _firstName = value;
               NotifyOfPropertyChange(() => FirstName);
           }
       }

And you have your property ready to link to a TextBox (x:Name item again) with Caliburn.Micro.

NotifyOfPropertyChange is a Caliburn.Micro method.

Download the zipped templates.

Save and extract from the zip file. Then import into Resharper Live Templates:

Resharper | Templates Explorer | Live Templates | select C# Scope | Import

I hope that these are useful for some Caliburn.Micro developers.

Advertisements

Binding Property Objects to WPF with Caliburn.Micro

Caliburn.Micro provides some powerful classes to help when working in WPF and I found it a very useful and rapid way to develop a WPF application for a client.

However, I found myself reproducing the same binding properties over and over (for example Foreground and Background colours for Labels, Buttons, TextBoxes, etc.). I thought that there must be a better way of handling the common properties for all these objects – rather than multiple Properties essentially doing the same thing. It seemed unlikely that there wasn’t a way of creating a class that could contain all the properties and be used to bind to the XAML objects.

The solution was suggested in this article by Colin Eberhardt.

Based on this I created the following class in the Models section of the project:

public class CommonControlProperties : PropertyChangedBase
{
 
    public CommonControlProperties()
        : this(new SolidColorBrush(Colors.Black), new SolidColorBrush(Colors.White))
    {
    }
 
    public CommonControlProperties(SolidColorBrush foreground, SolidColorBrush background)
    {
        Foreground = foreground;
        Background = background;
    }
 
    private SolidColorBrush _background;
    public SolidColorBrush Background
    {
        get { return _background; }
        set
        {
            _background = value;
            NotifyOfPropertyChange(() => Background);
        }
    }
 
    private SolidColorBrush _foreground;
 
    public SolidColorBrush Foreground
    {
        get { return _foreground; }
        set
        {
            _foreground = value;
            NotifyOfPropertyChange(() => Foreground);
        }
    }
      
}

This inherits Caliburn.Micro‘s PropertyChangedBase which provides the NotifyOfPropertyChange method. It implements only 2 properties for this example: Foreground and Background colours. Two constructors are provided – the basic just sets foreground to black and background to white by default, the second uses two SolidColorBrush items to set the foreground and background colours.

In the ViewModel I then declared an auto implemented Property of type CommonControlProperties:

public CommonControlProperties TestTextBox { get; set; }

This can be instantiated in the ViewModel constructor (or elsewhere):

TestTextBox = new CommonControlProperties();
OR
TestTextBox = new CommonControlProperties
{
    Background = new SolidColorBrush(Colors.Bisque),
    Foreground = new SolidColorBrush(Colors.Red)
};

Finally, the XAML code for the TextBox uses bindings to the ViewModel property and its relevant contained properties.

<TextBox x:Name="TestTextBox1" Background="{Binding TestTextBox.Background}" Foreground="{Binding TestTextBox.Foreground}" HorizontalContentAlignment="Left" Height="27" Margin="43,20,0,0" Grid.Row="3" TextWrapping="Wrap" Text="TextBox1" VerticalAlignment="Top" Width="132" FontSize="14" FontWeight="Bold"/>

This works as expected and allows a neat container for common properties that need to be bound to the XAML objects.

Obviously, this small class needs to be extended to contain all the properties that are useful for controlling the appearance of the visual Control.

SNIPPET: Prevent unwanted window close in Caliburn.Micro

I needed to avoid an unwanted Window close (using the [X] button in top right of Window).

The window is a UserControl inheriting the Caliburn.Micro Screen class (which is needed to provide the functionality).

public override void CanClose(Action<bool> callback)
{ // Prevents closing of window using the [X] button
     callback(_userExit); 
}

Simply override the Screen CanClose method.

_userExit is a private bool that is set in the code. Initialised to false and only set true if the user cicks the one button that is intended to close the window.

Method found on StackOverflow: http://stackoverflow.com/questions/8790526/caliburn-micro-cancel-window-close-from-viewmodel

Strange case of the displaced Combo Box dropdown

I was adding a User Login window for a WPF application in a project that uses Caliburn.Micro. This Window was opened during the Caliburn.Micro OnViewLoaded event and included a ComboBox for user name selection.

Everything worked as expected (though the User Login window appeared before the main view was displayed). However, when the ComboBox was clicked to display the dropdown list of user names the list appeared in the upper left of the screen.

A search showed that this was a known problem and much discussed with some solutions and suggestions. None that I found were specific to working with Caliburn.Micro but this reply on StackOverflow by Ken Salter was enough to provide a succint solution to the problem: http://stackoverflow.com/questions/1998024/wpf-combobox-dropdown-part-appears-in-the-wrong-place

I adapted the code to work in the OnViewLoaded event and this fixed the problem. The ComboBox worked as expected, plus the User Login window appeared after the Main View was displayed.

The code:

              private Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;
        private delegate void DelegateOpenWindow();
        private DelegateOpenWindow _delegateOpenUsersWindow;
 
        protected override void OnViewLoaded(object view)
        {
            base.OnViewLoaded(view);
            _delegateOpenUsersWindow = (ShowUserSelectWindow);
            _dispatcher.BeginInvoke(_delegateOpenUsersWindow);
        }
 
        private void ShowUserSelectWindow()
        {
            dynamic usersWindow = new ExpandoObject();
            usersWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            usersWindow.WindowStyle = WindowStyle.SingleBorderWindow;
            WindowManager.ShowDialog(new UsersViewModel(Events, WindowManager), null, usersWindow);
        }

Dispatcher is provided by the System.Windows.Threading library:

using System.Windows.Threading;

ShowUserSelectWindow is the method I have used to show the User LogIn window (named UsersViewModel). The Delegate and Dispatcher items are directly adapated from Ken Salters example.

Interestingly, one of the discussions included a comment from a Microsoft person where they said this bug would be fixed in .NET 4.5. My project is targetted at .NET 4.5, in VS2013 – Caliburn.Micro is version 1.5.2.0.

No doubt the code could be simplified further and perhaps Async / Await could be used – though I haven’t experimented with that yet.

Some further links on this subject:

http://stackoverflow.com/questions/4677701/c-sharp-strange-wpf-combobox-behavior

http://social.msdn.microsoft.com/forums/wpapps/en-us/545461b5-cf62-48e2-bcfb-2e872ecea639/wpf-tooltips-and-comboboxes-are-in-top-left-corner (the last post is the one that claims it is fixed in .NET 4.5).

https://www.devexpress.com/Support/Center/Question/Details/B202426