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

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.

Friday, 13 March 2009

Forcing OnPropertyChanged to update the UI

Having used my new Func<T, T> friend (see Action<T> and Func<T, TResult>) the bound TextBox refused to show the revised value. Even though OnPropertyChanged("...") had been called the property's "getter" was not called by WPF.

I don't really understand why.

To get round this problem I added a FormattingConverter to the TextBox called DoNothingConverter. Its presence is sufficient to ensure the UI updates.

public class DoNothingConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}

Action<T> and Func<T, TResult>

I wanted to pass a validation routine to my SetValue method that uses generics. So I used the Action delegate system.
protected void SetValue(T newValue, Action validate)
{
...
validate.Invoke(newValue);
...
}
That worked fine until I wanted to change the value (for formatting purposes). So I moved to using the Func delegate system instead. Since I want the result to be of the same type as the passed argument I used <T, T> instead of <T, TResult>.

protected T SetValue(T newValue, Func validate)
{
...
newValue = validate.Invoke(newValue);
...
}

Friday, 20 February 2009

WPF transparent windows and VNC

 
We've found that VNC doesn't transmit any info for transparent windows in a WPF app..
So.. when we use VNC for support.. we can't see :
 
The logon box
The popup menus
Any MessageBoxes
 
Not handy…. (not sure of the solution to this yet – might be something we can do with VNC.. might be a "support skin" change.