views:

438

answers:

3

In my XAML I get all customers by binding to a GetAll property:

<ListBox ItemsSource="{Binding GetAll}" 
     ItemTemplate="{StaticResource allCustomersDataTemplate}"
     Style="{StaticResource allCustomersListBox}">
</ListBox>

The GetAll property is an observable collection in my view model, which calls the Model to get all collection of customers:

public class CustomersViewModel
{
    public ObservableCollection<Customer> GetAll {
        get
        {
            try
            {
                return Customer.GetAll;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
}

If anything goes wrong in the model (badly formed XML file, etc.) then an exception bubbles up all the way to that GetAll property in the ViewModel.

First Question: I was surprised that XAML doesn't seem to do anything with the exception and just goes ahead and displays nothing. Is this by design? Is this part of the "decoupling approach"?

Second Question: This leads me to think I could handle the exception in XAML somehow, such as

Pseudo Code:

<Trigger>
    <Trigger.OnException>
        <TextBox Text="The customer data could not be loaded."/>
    </Trigger.OnException>
</Trigger>

Is something like the above code possible?

+1  A: 

Firstly, I would imagine that it is not intended that XAML exceptions should be caught. They exist more as a tool to help the developer see how they need to fix their XAML code, though they have to of course occur at runtime (initialisation) because of the dynamic nature of XAML markup

Saying that, you can handle XAML exceptions quite easily by wrapping the call to InitializeComponents within the constructor of your Windows class. You can then either catch all exceptions or specifically XamlParseException, whichever you find appropiate.

Example from this blog post:

public partial class Window1 : System.Windows.Window 
{
    public Window1()
    {
        try
        {
            InitializeComponent();
        }
        catch (Exception ex)
        {
            // Log error (including InnerExceptions!)
            // Handle exception
        }
    }
}
Noldorin
+1  A: 

My first thought is that you could use a ValueConverter, check for value==null and then set some arbitrary property of the view model, through a converter parameter. You could then use a regular property trigger in your xaml to show the error.

I'm pretty sure you could do this with a binding validator too though so I'd look there first.

EDIT: Yeah, take a look at http://msdn.microsoft.com/en-us/library/ms753962.aspx for an intro to binding validation rules,..that'll put you on the right path

Stimul8d
I needed this for validation, so thanks, but I think validation is separate from error handling, strange that error handling doesn't seem possible in XAML itself, you would think that is a common scenario: (1) get and display items, (2) if anything goes wrong, with getting data, display message #1 like this, (3) if anything else goes wrong, display message #2 like that, seems like this is the responsibility of the XAML UI, i.e. something the designer should be able to click together.
Edward Tanguay
Try going down the first route i mentioned then. If your going with a MVVM pattern this should be trivial to implement. You'll want something like a `BindingFailed` property on the class you're binding to which you then use in a property trigger in your XAML to modify the `ControlTemplate` of your `UIElement`. Or if you require more than two states of error implement the failure as an enum or your could even implement the `BindingFailure` property as something like `BindingException` of type `Exception` if you want to display the `ExceptionMessage
Stimul8d
+1  A: 

You can use the FallBackValue to provide a value to use in the binding if an error occurs. Other than using FallBackValue you can't handle exceptions in xaml.

You might also want to look into TargetNullValue which make a certain value equivalent to Null (e.g. if you set TargetNullValue=5 and your user enters 5 your setter will get Null and if your getter supplies Null the binding will display 5).

Bryan Anderson
Nice, hadn't come across these before. 1up for THAT!
Stimul8d