Category Archives: WPF

Do You DoEvents?

Often times during the development of enterprise software requirements arise stating that specific operations need to be handled both synchronously and asynchronously. A perfect example of this is printing. Perhaps a user wishes to print a document and wait for confirmation of a successful print operation before moving on to the next step of their business process. Or perhaps the user wants to request a print operation for multiple documents in a fire and forget fashion. In one case we should provide some sort of user interface cue as to the status of the print operation and in the other we just fire and forget, while hoping everything works out.

Thinking Synchronously

So we have a WPF window with a Print Button we also have a label to indicate the status of the running print job.

Some XAML

<Window x:Class="WpfApplication2.Print"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 Title="Print" Height="300" Width="300">
 <Grid>
 <StackPanel>
 <Button Command="{Binding Path=PrintCommand}">Print</Button>
 <Label Content="{Binding Path=PrintStatus}"/>
 </StackPanel>
 </Grid>
</Window>

Code Behind

using System.ComponentModel;
using System.Threading;
using System.Windows;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for Print.xaml
    /// </summary>
    public partial class Print : Window, INotifyPropertyChanged
    {
        #region Private Data Members

        private string mPrintStatus;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="Print"/> class.
        /// </summary>
        public Print()
        {
            InitializeComponent();
            DataContext = this;
            PrintCommand = new RelayCommand(PrintExecuted);
            PrintStatus = "Ready";
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Prints the specified parameter.
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void PrintExecuted(object parameter)
        {
            PrintStatus = "Print Executed";
            //Long Running Print Operatoin
            Thread.Sleep(1000);
            PrintStatus = "Print Completed";
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the print status.
        /// </summary>
        /// <value>The print status.</value>
        public string PrintStatus
        {
            get
            {
                return mPrintStatus;
            }
            private set
            {
                mPrintStatus = value;

                var handler = PropertyChanged;
                if (handler != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("PrintStatus"));
                }
            }
        }

        /// <summary>
        /// Gets or sets the print command.
        /// </summary>
        /// <value>The print command.</value>
        public RelayCommand PrintCommand
        {
            get;
            private set;
        }

        #endregion

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}

Looking at the code here you can see that the intended behavior is as follows.

  1. User Clicks Print Button
  2. PrintCommand is executed
  3. A label used to show the print status is updated from ‘Ready’ to ‘Print Executed’
  4. The long running Thread.Sleep is called simulating a synchronous print operation
  5. Once complete the status is again changed to ‘Print Completed’

This sequence of events does actually happen, the problem however is that it all happens within the execution scope of the  PrintExecuted method. Since this method is blocking until completed the user never sees the nice status updates we provide.

Before Click

Before Click

When the window is loaded the status is set to ‘Ready’ as seen in the image on the left. Once the print button is clicked we want to change the status to ‘Print Executed’ and finally when the PrintCommand is complete to ‘Print Complete’. However since the updates to the status all happen while the UI thread is blocking, the status of ‘Print Executed’ never makes it to the user. Instead the status will transition from ‘Ready’ directly to ‘Print Completed’  upon command completion. This presents a pretty serious issue if you need to give the user meaningful feedback about what is going on. On interesting way to get around this is to use DoEvents.

Do a What?

If you came to the wonderful world of WPF DoEvents was something new to you. In fact when I first presented this problem to a colleague with a strong Win Forms background he was quick to mention this. So what is it?

Take a look

To make a long story short DoEvents allows you to interrupt current event processing in order to process waiting events in the message pumps message queue. The good/bad news depending on your view of such things, is that if you need to replicated DoEvents in WPF you can. Because  WPF and WinForms both leverage the User32 message pump. the solution ends up to be very simple Lets take a look and what our PrintExecuted method might look like.

#region Private Methods

        /// <summary>
        /// Prints the specified parameter.
        /// </summary>
        /// <param name="parameter">The parameter.</param>
        private void PrintExecuted(object parameter)
        {
            PrintStatus = "Print Executed";
            Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { }));
            Thread.Sleep(1000);
            PrintStatus = "Print Completed";
        }

        #endregion

This approach give us the desired behavior of all of the status updates being presented to the user. Why this may not be a great illustration of proper use of an admitted hack. It is always good to have another tool in your toolbox.

Enjoy!

Binding WPF Style

This may be old news but it is exciting to me so I want to document it. Often times when working with the MVVM/Presentation Model Pattern you want to apply a style based on the state of your Model/Business Object. For example if a Business Object ‘IsNew’ you may want to apply a editable style to a TextBox control so the user can supply some data. Yet when the same Business Object ‘IsOld’ you may want disable a field preventing any data entry. My first thought was to use a converter to determine the style in a binding statement similar to this.

<TextBox Style={Binding Path=ViewModel.Customer, Converter={StaticResource StyleConverter}}/>

When data binding does its thing the Convert method will be passed the Customer Business Object. We can then inspect the Business Object to determine what style to apply to the TextBox. The rub however comes when we try to locate the style we want to apply. See code below.

        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var customer = value as Customer;
            if(customer != null && customer.IsNew)
            {
                //Locate and return the EditableTextboxStyle
                //Wait!!!! How?!!?
                return null;
            }
            return null;
        }

The crux of the problem is that most often styles exist as resources of your UserControl/Window/Page. In order to resolve these resources the converter will need a reference to the FrameworkElement that contains said resources. So how about this?.

<TextBox Style={Binding Path=ViewModel.Customer, Converter={StaticResource StyleConverter}}, ConverterParameter={Binding Path=DataContext}/>

And the converter….

           /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var customer = (Customer)value;
            var viewModel = (ViewModel)parameter;
            var view = viewModel.View;
            var fe = (FrameworkElement)view;

            if (customer != null && customer.IsNew)
            {
                return fe.TryFindResource("EditableTextboxStyle");
            }

            return fe.TryFindResource("NonEditableTextboxStyle");
        }

Though this seems like it may work(not really) there is one major issue that we run into. The ConverterParameter property in the binding statement is a CLR property that is it is not a DependencyProperty and because of this fact it cannot be data bound!

So just to restate the problem because most of the time I forget what problem I am actually trying to solve. I want a specific style to be applied to a TextBox based on the state of my Customer Business Object. For a converter to do this it needs a reference to the both the Business Object(to interrogate its state) as well as the View(To locate resources i.e. styles). So how can we pass two data bound objects to a converter? Well you cant! Not without some craziness.

Thankfully we have the Multibinding

I am not going to explain what you can read for yourself in the above article. I will however give you the code that did what I wanted to do 🙂 I am Felling a bit lazy tonight!

 <TextBox>
        <TextBox.Style>
            <MultiBinding Converter="{StaticResource StyleConverter}">
                <Binding Path="Customer"/>
                <Binding Path="DataContext"/>
            </MultiBinding>
        </TextBox.Style>
    </TextBox>

And the converter… When we multibinding we also have to use a multiconverter. So basically your converter has to implement IMultiConverter instead of IValueConverter. The only difference is that the first parameter of the Convert method is an array of objects. And in my case the first element in the array is a Customer object and the second a ViewModel! See below.

           /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object Convert(object [] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var customer = (Customer)value;
            var viewModel = (ViewModel)parameter;
            var view = viewModel.View;
            var fe = (FrameworkElement)view;

            if (customer != null && customer.IsNew)
            {
                return fe.TryFindResource("EditableTextboxStyle");
            }

            return fe.TryFindResource("NonEditableTextboxStyle");
        }

Like I said in the beginning this is far from groundbreaking but I thought it was worth a short post!

Tagged

GetIsInDesignMode(this)

Often times when trying to view a Window or UserControl in the WPF designer, the designer chokes and pukes all over your screen. Though your first instinct may be to abuse the Cider designers please refrain. Belive it or not it may be possible that it is not their fault! As it turns out, when Cider attempts to render your Window or UserControl it runs through a somewhat abbreviated version of its lifecyle. If you have code in any of these framework methods that, say, calls a web service or hits a database, Cider may not be able to resolve all of the resources needed. Sadly like many things in WPF the error messages are not always that helpful.

Thankfully there is a method in the System.ComponentModel namespace that can help.

private void Control_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
    if (DesignerProperties.GetIsInDesignMode(this))
    {
        return;
    }

    LoadModel();
}

Calling this method will return a boolean indicating weather or not the current control is being rendered in the designer or not. You can use this to wrap code that could potentially choke up the designer. Though this is not a perfect solution in terms of keeping your code clean. It will allow you to view your Windows or UserControls in the designer. And in many cases that is a must.

Tagged ,
Advertisements