Thursday, 16 April 2009

Regex

For some unknown reason people use Regex.

This is a useful link with examples from O'Reilly: Regex 101

Monday, 6 April 2009

Constructors

It became apparent the other day that I'd either forgotten some stuff about constructors or never knew it in the first place.

This web page has a good explanation of all the issues: Constructors

For example, what I hadn't really considered is that:
public class MySimpleClass
{
public MySimpleClass()
{
}
}

is converted by the compiler into:
public class MySimpleClass
{
public MySimpleClass() : base()
{
}
}
which makes a bunch of stuff easier to understand.

Similarly 'this' can be used to invoke constructors in the same class:
public class MySimpleClass : MyBaseClass
{
public MySimpleClass() : this(5)
{
}
public MySimpleClass(int x) : base(x)
{
}
}

DataTemplateSelector

UPDATE: There is an alternate technique described here and example code available from GoogleCode.

On our till roll I want to display each different category of product using a specific DataTemplate.

We start by defining the DataTemplates to be used in the usual way:

<DataTemplate x:Key="listBookingTemplate">...
<DataTemplate x:Key="listCCardTemplate">...
<DataTemplate x:Key="listCashTemplate">...
<DataTemplate x:Key="listDefaultTemplate">...

Then the DataTemplateSelector which is the link between the xaml DataTemplates and the C# class (TillRollTemplateSelector) that determines which template to use:

<ss:TillRollTemplateSelector 
 BookingTemplate="{StaticResource listBookingTemplate}" 
 CCardTemplate="{StaticResource listCCardTemplate}"
 CashTemplate="{StaticResource listCashTemplate}"  
 DefaultTemplate="{StaticResource listDefaultTemplate}" 
 x:Key="tillTemplateSelector" />

Then we need to wire up the template selector resource (tillTemplateSelector) to the ListBox that will display the data:

<ListBox Name="theTillRoll" Height="250" Width="330"
 ItemsSource="{Binding Source={StaticResource ViewModel}, Path=SaleItems}" 
 ItemTemplateSelector="{StaticResource tillTemplateSelector}"
 />

Finally, we define the C# class:

public class TillRollTemplateSelector : DataTemplateSelector
{
public DataTemplate BookingTemplate { get; set; }
public DataTemplate CashTemplate { get; set; }
public DataTemplate CCardTemplate { get; set; }
public DataTemplate DefaultTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is BookingLineItem) return BookingTemplate;
if (item is CashPaymentLineItem) return CashTemplate;
if (item is CCardPaymentLineItem) return CCardTemplate;
return DefaultTemplate;
}
}

The object item passed to the SelectTemplate method is of the same type as bound to the ListBox via the ItemsSource.

MultiBinding

I wanted to control the IsEnabled property of a Button based on the properties of two other controls.
Specifically I wanted to only enable the LogIn button if both the Site combobox and UserName textbox had a value available.

I created a MultiBinding for the Button like this:
<Button.IsEnabled>
   <MultiBinding Converter="{StaticResource loginConverter}">
      <Binding ElementName="xSite" Path="SelectedIndex"/>
      <Binding ElementName="xUsername" Path="Text"/>
   </MultiBinding>
</Button.IsEnabled>

And a IMultiValueConverter like this:
public class LoginConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      // SelectedIndex of the ComboBox
      int selectedIndex = (int)values[0];
 
      // Length of Text in TextBox
      int selectedLength = ((string)values[1]).Length;
 
      // Only enable Button if both Combo and TextBox have data
      if (selectedIndex == -1 || selectedLength==0)
      {
         return false;
      }
      else
      {
         return true;
      }
   }
   public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
   {
      throw new NotImplementedException();
   }
}

The array of object[] values are presented in the same order as the Bindings within the MultiBinding.

Finally here is an example of using MultiBinding with StringFormat.