Posts Tagged Xaml

WPF : A Future Xaml Home For LOB and IE

stockxpertcom_id21167841_jpg_96cea7cca529ddc8485f5b21de62e2f6I was recently asked to provide my humble opinion on the future of WPF , literally how it should it be charted going forward. This is my utopian vision for WPF going forward.

I am going to answer that question as if I had received the the Wonka Golden Ticket and was able to go to Microsoft and ultimately become a sort of  Scott Gu of  Microsoft and direct the future of WPF, here is what I would order the Umpa Lumpas to do. To be clear, I only use the term Umpa Lumpa to mean a hard diligent worker at Microsoft and not any short and blue person or a minion doing one’s evil bidding; heck a combination of both but better paid. 

Before one can come to grips with my future utopia vision of what WPF would be, one would have to look into the past to see what Xaml technologies has provided the the Line Of Business (LOB) developer. For that is what I am, a Line of Business developer who gets paid to create business applications to the highest bidder. My ego is inflated enough to think that my services actually go to a “highest bidder” , but let us not touch that fourth wall of  my reality ok?

Where Have You Been Xaml?

Currently a LOB developer is basically in charge of bringing data and all related business rules to the corporate environs. Historically that vehicle has been Xaml used in WPF, Silverlight and just recently Windows 8 tablet.  All of them use subtle flavors of Xaml to achieve that work. Xaml is great because through the use of MVVM and a kick ass way of leveraging a graphical based solution to displaying that data, it has provided the developer with a rich toolset bar none in the industry. Let me repeat that, bar none people.

What is my anecdotal evidence?

I was tasked with bringing such a graphical solution to a cable industry partner. To anyone who is not aware of the cable industry, it is, now, a few providers spread out over the country, if not the world, and they are frankly a Java shop. The Oracle flag flies over their realm and very few if any .Net projects are done within the differing companies.

With that backdrop in mind, Java, the small company I ended up working for was seeking to bring tools to the major cable vendors. One of the tools needed a graphical front end to allow for a back and forth way of editing business related data for their end clients. There was no Java, still isn’t, technology which could fill that gap, only a Xaml solution in the form of the Silverlight tool provided the best working solution and they took it.

Take out the Silverlight of the last story and keep in mind Xaml and WPF. For what they needed was a way to bring a rich client experience to the end user and there was a viable Xaml based solution available to them.

Xaml As a Means and Not an End

The LOB business developer needs to be able to bring that graphical data experience to the table. “What about the Javascript solutions out there?”, one might ask? Javascript and HTML 5 solutions have come a long way, but frankly any developer who has spent anytime dealing with the non strongly typed environment comes away with a bad taste in their mouth due to the unwieldy nature of any app which grows past a certain size and cannot be managed.

Javascript solutions are frankly unmanageable at a certain point and any developer knows and dreads that.

If only businesses could understand that WPF in a managed language is the best use of large scale applications and providing a rich, yes rich, client experience to the end user, it would go a long way.

WPF’s Achille’s Heal AND HOW THE CLOUD COULD RESCUE IT

Very few businesses want to install, and update applications to the end user. Period end of story.

That is why Silverlight to both the developer and businesses was so appealing. Not that it would work cross browser or anything else, just that it provided a vehicle to supplant IT and go around having to install applications on locked up corporate PCs.

From the cloud came a solution to avoid the IT department and it was, and still is, the best way to bring data and more critically the viewing of said data to the corporate person.

WPF Future

That leads me here, to my goal of WPFs future. If I could provide the corporate end user with a way to bring a rich graphical experience without having to install it, that would be my goal.

How would I achieve it?

I would bake a WPF visual experience into IE. Where IE under certain approved circumstances would provide a gateway to a rich client experience. As a developer I don’t care what IE has to do, just that it would allow me to interact with a client at the end of the tunnel from the server without having to get my feet wet in Javascript and HTML 5.

As a LOB experience, I don’t care that this it would not be available outside IE; because my target audience is required to to have IE for this business purpose. In as much as we provide a PC, not a Mac to the corporate user, we provide a specific browser.

If I could provide the best of WPF, in a better browser experience (not Silverlight) that is what I would be the task the Umpa Lumpas would create.

WPF Realities

The reality is that someone like a Scott Gu would have to champion such a project at Microsoft. This person would have to sell the idea of a managed GUI environment (similar to C# being managed and not C++)  to the browser based LOB customer as a WPF Future solution.

But I truly believe it would be a game changer in the business world…just that I don’t have the golden ticket and my voice is just one out here on the Western Front of the internet at this time.

Share

Tags: ,

Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding.

BasicBindingUpdate 11.07.2013 : Added ICommanding example.
Update 10.25.2013 : Added how to use the CallerMemberName attribute with INotifyPropertyChanged in .Net 4.

While answering a question on StackOverflow I ran across a situation where the user was having troubles due to binding to a view model which was statically initiated in Xaml. While there is nothing wrong with creating the VM in Xaml, it can miss some benefits for most control and page situations where the all controls want to access one source of data. This article describes and provides example code to creating the view model in the code behind which I tend to prefer over the others methods.

Create a .Net 4 and Above VM

The view model adheres to the standard where it implements INotifyPropertyChange. The following ViewModel implements it using the .Net 4.5 way with the CallerMemberName attribute which saves us from having to explicitly define it on every member call. (If you are using .Net 4, add the Nuget Package: Microsoft BCL into you project to use CallerMemberName attribute).

Note for reference there is a situation below where we actually do specify the property name but it is to create in a change notification on another property.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace SO_WPF.ViewModels {

public class MainVM : INotifyPropertyChanged 
{

    private List<string> _Members;
    private int _MemberCount;
    private bool _IsMembershipAtMax;
    public bool IsMembershipAtMax 
    {
        get { return MemberCount > 3; }
    }
    public int MemberCount 
    { 
        get { return _MemberCount; }
        set
        {
            _MemberCount = value; 
            OnPropertyChanged();
            OnPropertyChanged("IsMembershipAtMax");
        } 
    }

    public List<string> Members 
    { 
        get { return _Members; }
        set { _Members = value; OnPropertyChanged(); } 
    }
    public MainVM()
    {
        // Simulate Asychronous access, such as to a db.

        Task.Run(() =>
                    {
                        Members = new List<string>() {"Alpha", "Beta", "Gamma", "Omega"};
                        MemberCount = Members.Count;
                    });
    }
    /// <summary>Event raised when a property changes.</summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>Raises the PropertyChanged event.</summary>
    /// <param name="propertyName">The name of the property that has changed.</param>
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}
}

Main Page Code Behind

We now need to hook up the main page view model to the main page. To do that we will do two things, one, make a non INotifyPropertyChanged property on the class which will hold our view model. Two we will instantiate it, hook it up to the page’s data along with our property. Doing that ensures that everything on our page will get access to our view model, thanks to the data context and how controls inherit their parents data context.

using SO_WPF.ViewModels;

namespace SO_WPF
{
    public partial class MainWindow : Window
    {

        public MainVM ViewModel { get; set; }

        public MainWindow()
        {
            InitializeComponent();

            // Set the windows data context so all controls can have it.
            DataContext = ViewModel = new MainVM();

        }

    }
}

Xaml

Now in the xaml we can simply bind to the View Models properties directly without any fuss.

<Window x:Class="SO_WPF.MainWindow"
        xmlns:viewModels="clr-namespace:SO_WPF.ViewModels"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        d:DataContext="{d:DesignInstance {x:Type viewModels:MainVM}}"
        Title="MainWindow"
        Height="300"
        Width="400">

<StackPanel Orientation="Vertical">
    <ListBox Name="lbData"
                ItemsSource="{Binding Members}"
                SelectionMode="Multiple"
                Margin="10" />

    <Button Height="30"
            Width="80"
            Margin="10"
            Content="Click Me" />
</StackPanel>

</Window>

In the above code we bind the Members to the listbox just by specifying the Members property name. As to the highlighted lines, I have added them as a debug design option. That lets Visual Studio and Blend know that our data context is our MainVM. That allows for the editor to present us with the options of data binding to the appropriate items, and not having it blank.

This has been a simple example, but a powerful one which can be used as a binding strategy for any WPF, Silverlight or Windows Phone Xaml based applications in C#.

Note though it is not shown, sometimes in styles one needs the element name to bind to, where the data context will fail due to the nature of the style binding, the above page we would bind to the page name as provided (“MainWindow”) and then the property name as usual!

Extra Credit ICommanding

I won’t go into much detail about commanding, but the gist is that the ViewModel is not directly responsible for actions which can happen due to the ICommanding process, but allow for binding operations to occur against those actions and those actions are performed elsewhere usually on a view.

Below is our view model with the commanding public variables which can be consumed by controls (or other classes which have access to the VM).

public class MainVM : INotifyPropertyChanged
{
    #region Variables
       #region Commanding Operations

    public ICommand ToggleEditing { get; set; }
    public ICommand ReportError   { get; set; }
    public ICommand CheckSequence { get; set; }

       #endregion
       #region Properties
    public string ErrorMessage { // the usual INotifyProperty as shown before }
       #endregion
    #endregion
}

Then on our main page which consumes the view model we then process those requests by creating methods to fulfill those operations. Note that the example below references properties on the VM which were not shown in the example,
but that is not important in this article. But one variable is shown and that is the error message. This allow anyone to push an error using the commanding to the viewmodel which is subsequently shown. That is a peek at the power of commanding right there to allow a dependency injection of setting an error variable to be done outside the VM but used by those which consume the VM!

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();

        // Set the windows data context so all controls can have it.
        DataContext = ViewModel = new MainVM();

        SetupCommanding();
    }

    private void SetupCommanding()
    {
        // Commanding using OperationCommand class
        ViewModel.ToggleEditing         = new OperationCommand((o) => ViewModel.IsEditing = !ViewModel.IsEditing);
        ViewModel.ReportError           = new OperationCommand((o) => ViewModel.ErrorMessage = (string)o);
        ViewModel.CheckSequence         = new OperationCommand(CheckSequences, CanExecute);

    }

     private void CheckSequences(object obj)
     {
        ...
     }

    private bool CanExecute(object obj)
    {
        return !ViewModel.UnsavedsExist;
    }
}

Finally the ICommanding class used.

public class OperationCommand : ICommand
{

    #region Variables

    Func<object, bool> canExecute;
    Action<object> executeAction;

    public event EventHandler CanExecuteChanged;

    #endregion

    #region Properties

    #endregion

    #region Construction/Initialization

    public OperationCommand(Action<object> executeAction)
        : this(executeAction, null)
    {
    }

    public OperationCommand(Action<object> executeAction, Func<object, bool> canExecute)
    {
        if (executeAction == null)
        {
            throw new ArgumentNullException("Execute Action was null for ICommanding Operation.");
        }
        this.executeAction = executeAction;
        this.canExecute = canExecute;
    }

    #endregion

    #region Methods

    public bool CanExecute(object parameter)
    {
        bool result = true;
        Func<object, bool> canExecuteHandler = this.canExecute;
        if (canExecuteHandler != null)
        {
            result = canExecuteHandler(parameter);
        }

        return result;
    }

    public void RaiseCanExecuteChanged()
    {
        EventHandler handler = this.CanExecuteChanged;
        if (handler != null)
        {
            handler(this, new EventArgs());
        }
    }

    public void Execute(object parameter)
    {
        this.executeAction(parameter);
    }

    #endregion
Share

Tags: , , , , , ,

Xaml: Call Binding Converter Without Defining StaticResource in Xaml Thanks to Markup Derived Base Class in C#

When developing Xaml everyone has to create a converter in code at some point for binding data conversion. Of course to expose that converter to the Xaml bindings one has to specify it in as a static instantiated resource to be available to the binding call(s). In this post I demonstrate how to remove the middle man of that Xaml static instantiation to reside in a common base class which can be derived by the existing converters with minimal change. Once that is in place the converter will also be a MarkupExtension which can be called directly within the { } brackets such as shown on the highlighted line:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:converters="clr-namespace:Omega.Operation.Converters"
        ...
        >

<DataGrid Grid.Row="1"
          Visibility="{Binding IsEditing, 
                       Converter={ converters:BooleanToVisibilityReverseConverter } 
                      }">
Convert the Converter

The change to any converter is quite minimal and once the base class (shown later) is in place it is simply a one line change. Here is the code for the converter used above.

The highlighted line shows the change;  simply adding the base class to its definition with a generic template of itself:

namespace Omega.Operation.Converters
{
/// <summary>Does the reverse where if a value is true the control is collapsed and if false the control is visibile</summary>
public class BooleanToVisibilityReverseConverter : CoverterBase<BooleanToVisibilityReverseConverter>, 
                                                   System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (value is bool && (bool)value) ? Visibility.Collapsed : Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value is Visibility && (Visibility)value == Visibility.Collapsed;
    }
}
}
Base Class Magic

The following generic base class will instantiate the derived class and return a single static instance of the derived class for usage in Xaml:

/// <summary>
/// This creates a Xaml markup which can allow converters (which inheirit form this class) to be called directly
/// without specify a static resource in the xaml markup.
/// </summary>
public  class CoverterBase<T> : MarkupExtension where T : class, new()
 {
    private static T _converter = null;

    public CoverterBase() { }

    /// <summary>Create and return the static implementation of the derived converter for usage in Xaml.</summary>
    /// <returns>The static derived converter</returns>
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return _converter ?? (_converter = (T) Activator.CreateInstance(typeof (T), null));
    }
}

With the base class providing the required implementation of for the MarkupExtension, the derived class can be simply called in the Xaml and avoiding having to use the static resource implementation.

Things to Consider
  • Works in WPF, Silverlight, Windows Phone 8 (WP8), and Windows 8 Store apps.
  • Visual Studio’s Xaml designer may give blue squiggly warning “No constructor type for ‘xxx’ has 0 parameters.”. Ignore that warning…for there is a default constructor which doesn’t have to be defined in C#.
Share

Tags: ,

Silverlight: Xaml Blend Namespace Error Not Resolved

XAML Namespace http://schemas.microsoft.com/expression/blend/2008 is not resolved.

This error can occur when certain Xaml elements added by blend have not been properly ignored during non design/debug situations and Blend or Visual Studio reports such error.

To resolve the error one must add the mc:Ignorable attribute to the namespace declarations to inform the Xaml compiler to ignore a specific specified namespace at appropriate times. T0 fix the above error where the blend namspace is qualified by d one needs to ingore D as shown on the highlighted line:

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"

How Does This Happen?

I ran into this recently when Blend 4 added Xaml to allow me to populate (bind generated data) to a datagrid during design time (only in blend mind you) to work with the design data. Of course the blend namespace was there, but it never added the ignorable. It actually failed due from this line because its bringing in the blend namespace here, though I was never informed of the exact line.

<Grid x:Name="LayoutRoot"
      HorizontalAlignment="Stretch"
      d:DataContext="{d:DesignData /SampleData/HomeViewModelSampleData.xaml}">

One can see the ‘d’ namespace qualifier which relates to the blend namespace declaration as shown above. Since its job is to bring in sample data, that obviously should not be expressed during runtime and was not ignored.

Once one understands this situation the resolution seems trivial but it is one which has to be learned.

Share

Tags: , ,