3

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.

kmontgom
  • 1,419
  • 13
  • 18

3 Answers3

2

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.

dharmatech
  • 8,979
  • 8
  • 42
  • 88
2

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.

Anderson Imes
  • 25,500
  • 4
  • 67
  • 82
  • Thanks. I have listened to both those podcasts, and actually decided to investigate fluent silverlight because of them. WPF contains lots of cool things -- its just a matter of figuring out how best to use (and package) them. At the risk of dating myself, I had thought about an MFC equivalent to WPF, but the fluent interface seems like a better approach. Does anybody else know of other balanced appraisals of WPF? I.e. neither completely negative nor completely blindly accepting? – kmontgom Aug 28 '09 at 19:41
  • I've not heard of much. Most people are embracing Xaml that I've ran across. It's really bad at all. I like it a lot now, personally. I think if I had to go to a fluent interface I would likely find it cumbersome, if you can believe that. – Anderson Imes Aug 29 '09 at 05:48
  • 2
    I like working with XAML but I would like the idea of strong typing and other types of compile type checking that Fluent Interface or any other code based method could offer. The words part of dealing with data binding XAML is that you feel like your back on the Web doing trial and error code and run the application to see if it works type of programming. I'd rather leave that to testers but even worse the testers don't even see a binding error by default so we have to introduce our own handling of WPF errors to get tester feedback from them. Bummer. – jpierson Apr 02 '11 at 05:56
  • @jpierson: I definitely feel your pain here. You can look at the strongly typed views in ASP.NET MVC and definitely see the value there. That isn't a design goal of WPF, though, especially with regards to MVVM. Views are meant to be a little bit more fluid and reusable across types. Creating lookless underpinnings and type-agnostic views is a value in WPF. It has the drawbacks you mentioned, and I agree, but it's just not a design goal met by WPF out of the box. Being able to do view-first development is pretty unique and I see a lot of value there. – Anderson Imes Apr 02 '11 at 13:23
1

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

Adam Mills
  • 7,719
  • 3
  • 31
  • 47