26 September 2011

HTML - Fix the 'click to activate and use this control' browser behavior

In recent years browsers require you to click embedded HTML objects before they can become active. Opera will display a tooltip with the message 'Click to activate and use this control' when you hover over one before you clicked it. This behavior can be corrected though, like this:

Create a JavaScript file — I called it FixActivate.js — and put this in it:
var objects = document.getElementsByTagName("object");
for (var i = 0; i < objects.length; i++) {
  objects[i].outerHTML = objects[i].outerHTML;
}
Then, at the bottom of any HTML page containing embedded objects, include this file like so:
<script src="FixActivate.js" type="text/javascript"></script>
Now when the page is loaded, the embedded objects are immediately active.

18 September 2011

WPF - Bind to a property in code-behind

In some case, like when you have a ComboBox inside a DataTemplate, you can't set a property, the ItemsSource in this case, from code-behind. You have to use a binding to set this property, and you can like this:

In code-behind, create a public property and set that instead:
public BindingList ProductList { get; private set; }

Then use a binding to that property to set the property of the element:
<DataTemplate>
  <this:ComboBox
        ItemsSource="{Binding ProductList,
        RelativeSource={RelativeSource  Mode=FindAncestor,
        AncestorType={x:Type this:ucStoreVisit}}}" />
</DataTemplate>

And it'll work!

15 September 2011

.NET - Output an exception including it's inner exceptions

Often when outputting an exception message, you get "see inner exception" or "one or more errors occured" for an aggregate exception. It would be convenient to, when outputting error messages, you get those attached. This extension does that. It keeps going down the inner exceptions until there are no more, and outputs them line by line:

/// <summary>
/// Returns a string that contains the message and inner messages.
/// </summary>
public static string GetFullMessage(this Exception source)
{
    var result = new StringBuilder();
    var ex = source;

    try
    {
        while (ex != null)
        {
            if (result.Length > 0)
                result.Append(Environment.NewLine);

            result.Append(ex.Message);

            //It's handy to get the actual errors when these errors occur.
            if (ex is ReflectionTypeLoadException)
            {
                result.AppendLine("Loader exceptions:");
                var typeErrors = (ex as ReflectionTypeLoadException)?.LoaderExceptions;

                if (typeErrors != null)
                    foreach (var typeError in typeErrors)
                        result.AppendLine(typeError?.Message);
            }
            else if (ex is AggregateException)
            {
                result.AppendLine("Aggregate exceptions:");
                var inner = ex.InnerException;

                while (inner != null)
                {
                    result.AppendLine(inner.Message);
                    inner = inner.InnerException;
                }
            }

            ex = ex.InnerException;
        }
    }
    catch (Exception ex2)
    {
        result.AppendLine("The following error occured in GetFullMessage:");
        result.AppendLine(ex2?.Message);
    }

    return result.ToString();
}

08 September 2011

WPF - ComboBox or DataGridComboBoxColumn with "none" option

Something trivial that's currently not possible with the ComboBox or DataGridComboBoxColumn (Toolkit) controls of WPF is adding a "none"-option on top op their dropdown without having to add it to the ItemsSource, which would be really bad design. So this is how I implemented this common requirement:

The converter

A converter is needed to make sure the none-option actualy sets the bound property to null. Without it the property would simply not change.
I created one called NullObjectConverter. It's Convert-method simply returns the value-parameter.
The ConvertBack-method does this:
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
  if (value == null || value.GetType() != targetType)
    return null;
  else
    return value;
}
I've put the resource for it in the resources of the App-class, so I don't have to do that in every XAML-file that needs it:
<this:NullObjectConverter x:Key="convNull" />

The XAML

This is my XAML for a DataGridComboBoxColumn. Notice how it uses the converter above. Important is that it's ItemsSource is a CompositeCollection composed from the none-option and the actual list of options:
<toolkit:DataGridComboBoxColumn Header="Store"
         SelectedValueBinding="{Binding Store,
                                Converter={StaticResource convNull}}">
  <toolkit:DataGridComboBoxColumn.ItemsSource>
    <CompositeCollection>
      <ListBoxItem>(none)</ListBoxItem>
      <CollectionContainer x:Name="cboStoreCollection" />
    </CompositeCollection>
  </toolkit:DataGridComboBoxColumn.ItemsSource>
</toolkit:DataGridComboBoxColumn>
The none-option will arrive in the converter as a ListBoxItem while the target type will be the type of the bound object, and therefore the converter will send NULL to the bindings' source when it's selected.

Finally, notice that the CollectionContainer that contains the actual list of options gets it's items in the code-behind, and therefore has a name:
cboStoreCollection.Collection = mStores;