Question

As part of my on-going attempt to come to terms with WPF/XAML, I've become interested in the application of fluent interfaces to UI coding.

I am aware of Fluent Silverlight (http://code.google.com/p/fluent-silverlight/), but I can't seem to find anything equivalent for WPF.

Just as a personal note, I'm finding it very difficult to buy into doing everything in a combination of XAML and C#/MVVM. It just seems to me that there are certain aspects of UI programming (e.g. data binding) that are better expressed in code than in declarative XAML.

A fluent WPF interface would seem to be just the thing to accomplish these goals.

Was it helpful?

Solution

Fluent API for building Commands in WPF http://code.google.com/p/present/

OTHER TIPS

On a recent podcast of Herding Code: http://herdingcode.com/?p=212 one of the guests discusses that they attempted a fluent interface for creating WPF UIs. It's possible one of them could make what they have done available.

Incidentally, this same podcast and the one before it (http://herdingcode.com/?p=208) speak to your concerns about code first vs. view first and why it is advantageous to concentrate on xaml.

The arguments for are primarily about making UIs "Blendable" (being able to design them in Microsoft Expression Blend) by a designer in addition to the testability of your code. A code-based approach sort of diminishes this ability if you aren't very careful.

You are not alone in your misgivings. Hopefully these podcasts will help you make a decision.

As I run into parts of WPF which I'd prefer to program in a fluent style, I add supporting extension methods to a personal utility assembly.

For example, here's a program which demonstrates the TaskbarItemInfo ProgressValue and ProgressState properties. This version is written in a standard non-fluent way.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Shell;

namespace TaskbarItemProgress
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            TaskbarItemInfo = new TaskbarItemInfo();

            TaskbarItemInfo.ProgressValue = 0.5;

            var stackPanel = new StackPanel();

            Content = stackPanel;

            var normalButton = new Button() { Content = "Normal" };
            normalButton.Click += (s, e) => 
                TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Normal;
            stackPanel.Children.Add(normalButton);

            var pausedButton = new Button() { Content = "Paused" };
            pausedButton.Click += (s, e) =>
                TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Paused;
            stackPanel.Children.Add(pausedButton);

            var errorButton = new Button() { Content = "Error" };
            errorButton.Click += (s, e) =>
                TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Error;
            stackPanel.Children.Add(errorButton);

            var indeterminateButton = new Button() { Content = "Indeterminate" };
            indeterminateButton.Click += (s, e) =>
                TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Indeterminate;
            stackPanel.Children.Add(indeterminateButton);

            var noneButton = new Button() { Content = "None" };
            noneButton.Click += (s, e) =>
                TaskbarItemInfo.ProgressState = TaskbarItemProgressState.None;
            stackPanel.Children.Add(noneButton);

            var increaseButton = new Button() { Content = "Increase" };
            increaseButton.Click += (s, e) => TaskbarItemInfo.ProgressValue += 0.10;
            stackPanel.Children.Add(increaseButton);

            var decreaseButton = new Button() { Content = "Decrease" };
            decreaseButton.Click += (s, e) => TaskbarItemInfo.ProgressValue -= 0.10;
            stackPanel.Children.Add(decreaseButton);
        }
    }
}

Here's the fluent version:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Shell;
using FluentWpf;

namespace TaskbarItemProgress
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            TaskbarItemInfo = new TaskbarItemInfo();

            TaskbarItemInfo.ProgressValue = 0.5;

            Content = new StackPanel()
                .AddChildren(
                    new Button() { Content = "Normal" } 
                        .AddClick((s, e) => TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Normal),
                    new Button() { Content = "Paused" } 
                        .AddClick((s, e) => TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Paused),
                    new Button() { Content = "Error" } 
                        .AddClick((s, e) => TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Error),
                    new Button() { Content = "Indeterminate" } 
                        .AddClick((s, e) => TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Indeterminate),
                    new Button() { Content = "None" } 
                        .AddClick((s, e) => TaskbarItemInfo.ProgressState = TaskbarItemProgressState.None),
                    new Button() { Content = "Increase" } .AddClick((s, e) => TaskbarItemInfo.ProgressValue += 0.10),
                    new Button() { Content = "Decrease" } .AddClick((s, e) => TaskbarItemInfo.ProgressValue -= 0.10));
        }
    }
}

The fluent version is employing two extension methods, AddChildren (instead of Children.Add) and AddClick (instead of Click += ...).

The program looks like this:

enter image description here

I keep my personal FluentWpf library on github.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top