The adapter pattern and presenter-first UIs


The adapter pattern provides a technique to bind together the presenter logic and the UI screens of a presenter-first model (and other loosely coupled models) of user interface implementation. An example follows.

An application to double an integer requires a presenter function to perform the doubling on request:

public class Presenter
{
    public IInput Input { get; set; }
    public IOutput Output { get; set; }

    public void PerformDoubling()
    {
        int inputValue = Input.GetValue();
        int result = inputValue * 2;
        Output.SetValue(result);
    }
}

The presenter is using interfaces to access the user interface – which allows presenter unit tests to be built via mocks independent to the development of the UI:

public interface IInput
{
    int GetValue();
}

public interface IOutput
{
    void SetValue(int newValue);
}

Binding the interfaces to a deployed UI can then take the form of UI-specific adapters to the IInput and IOutput interfaces. I.e. for a Window1 class containing input and output accessors (implemented using explicit marshalling as described in this blog entry):

public partial class Window1 : Window
{
    ...

    public String ThreadSafeGetInputValue() ...
    public void ThreadSafeSetOutputValue(String newValue) ...
}

The following two adapters can be used to convert the UI to match the required interface without the need to modify the UI code. (Null and error checking has been excluded below to reduce code footprint:)

public class AdapterIInputWindow1 : IInput
{
    private Window1 Window1 { get; set; }

    public AdapterIInputWindow1(Window1 wrappedWindow)
    {
        Window1 = wrappedWindow;
    }

    // IInput implementation - excluding error checking
    public int GetValue()
    {
        int result = Convert.ToInt32(Window1.ThreadSafeGetInputValue());
        return result;
    }
}


public class AdapterIOutputWindow1 : IOutput
{
    private Window1 Window1 { get; set; }

    public AdapterIOutputWindow1(Window1 wrappedWindow)
    {
        Window1 = wrappedWindow;
    }

    // IOutput implementation - excluding error checking
    public void SetValue(int newValue)
    {
        Window1.ThreadSafeSetOutputValue(newValue.ToString());
    }
}

Finally the UI can initialize its presenter and set the IInput and IOutput interfaces to the appropriate adapters:

public partial class Window1 : Window
{
    private Presenter Presenter { get; set; }

    public Window1()
    {
        InitializeComponent();

        Presenter = new Presenter();
        Presenter.Input = new AdapterIInputWindow1(this);
        Presenter.Output = new AdapterIOutputWindow1(this);
    }


    public void XamlAction(object sender, EventArgs args)
    {
        Presenter.PerformDoubling();
    }
    ...
}
Advertisement

Use explicit marshalling to update a WPF UI from a non-UI thread


One option for updating a WPF UI from a non-UI thread (including a background worker) is to perform explicit marshalling using the dispatcher. A simple example follows.

A separate blog entry details how to update a UI using a background worker’s implicit marshalling.

Lets assume there is a C# window mediator class that has a reference to a pair of WPF controls – one for user input and one for user reporting. The WPF window constructs the mediator and sets the two control properties during its construction. Two functions provide access to the data and may be called from any thread:

public partial class MainWindow : Window
{
    private WindowMediator m_mediator = null;

    public MainWindow()
    {
        InitializeComponent();
   
        m_mediator = new WindowMediator();

        // Controls declared in the window's XAML
        m_mediator.IncomingDataControl = m_xamlTextBox;
        m_mediator.ReportDataControl = m_xamlTextBlock;
        ...
    }
    ...
}

public class WindowMediator
{
    // Controls.  A TextBox to retrieve data and a TextBlock to report data
    public TextBox IncomingDataControl { private get; set; }
    public TextBlock ReportDataControl { private get; set; }

    // Access functions to retrieve and set data (also see below)
    public String GetIncomingData(bool reformat) { ... }
    public void SetReportData(String newReport) { ... }
}

When updating the values of a WPF control, the code needs to be executed on the UI thread – i.e. the thread that owns the WPF control. The control’s dispatcher provides a function CheckAccess (which is the equivalent of the Windows Forms property InvokeRequired) to determine whether the call is currently executing on the UI thread.

If not – the Invoke method of the dispatcher can be used to execute a delegate on the appropriate thread. The Action framework class can be used to generate a Delegate from the current method (or from an anonymous method) and pass the parameters across:

public void SetReportData(String newReport)
{
    if (!ReportDataControl.Dispatcher.CheckAccess())
    {
       // Switch threads and recurse
       ReportDataControl.Dispatcher.Invoke(
          System.Windows.Threading.DispatcherPriority.Normal,
          new Action<String>(SetReportData), newReport);
    }
    else
    {
        ReportDataControl.Text = newReport;
    }
}

A similar method can be used to retrieve data from a WPF control. The generic framework class Func can be used to add a return type:

public String GetIncomingData(bool reformat)
{
    String result = "";

    if (!IncomingDataControl.Dispatcher.CheckAccess())
    {
       // Switch threads and recurse
       result = (String) IncomingDataControl.Dispatcher.Invoke(
          System.Windows.Threading.DispatcherPriority.Normal,
          new Func<bool, String>(GetIncomingData), reformat);
    }
    else
    {
        if (reformat)
        {
             result = "--" + IncomingDataControl.Text;
        }
        else
        {
             result = IncomingDataControl.Text;
        }
    }

    return result;
}

Update UI from background worker thread without explicit marshalling


It is possible to update the UI thread from a background worker thread without the need to explicitly marshal the call across to the UI thread. An example follows.

A separate blog entry details how to update a UI using explicit marshalling.

The background worker member is used to perform potentially long lasting non-UI activities:

    private BackgroundWorker m_bw = new BackgroundWorker();

When starting the background worker (e.g. in the instance constructor after InitializeComponents for a WPF application) set the flag to indicate that the worker reports progress and add a ProgressChangedEventHandler:

    m_bw.DoWork += bw_DoWork;
    m_bw.WorkerReportsProgress = true;
    m_bw.ProgressChanged += bw_ProgressChanged;
    m_bw.RunWorkerAsync();

In the background worker activity when you want to update the UI call the ProgressChanged method on the background worker using the overload to pass a state object:

    int progress = 50;
    var state = new KeyValuePair<string, string>("Status", "Still working");
    m_bw.ReportProgress(progress, state);

The event that this call raises is raised on the thread that created the background worker – so in this case the UI thread – which means that implicit marshalling has occurred. In the ReportProgressEventHandler you can then directly update the UI controls:

    void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        ...

        var state = (KeyValuePair<string, string>) e.UserState;
        m_xamlProgress.Text = e.ProgressPercentage + "%";
        m_xamlStatus.Text = "Status: " + state.Value;

        ...
    }

This approach separates the creation of the update data from the activity of updating the controls – providing an implicit interface between the worker thread and the UI thread.

In more complex scenarios where threads that have not been created by the UI thread need to update controls the mechanism of Control.InvokeRequired followed by use of Invoke / Dispatcher can be used.