Pages

Thursday, 20 August 2009

How to set a property to a DynamicResource reference in code

We recently needed to create a control in code and apply a style. The best reference I could find was this one at Josh Smith's blog: How to set a property to a DynamicResource reference in code

Our own example in XAML and C# looked like this:
<ItemsControl Style="{DynamicResource POSDatesTimesButtonItemsControlStyle}"

FrameworkElementFactory itemsControlElement = new FrameworkElementFactory(typeof(ItemsControl));
itemsControlElement.SetResourceReference(ItemsControl.StyleProperty,
"POSDatesTimesButtonItemsControlStyle");

Monday, 27 July 2009

Syncronous ProgressBar status updates

Within our application we make calls to server services both synchronously and asynchronously. There are some service calls that we want to make synchronously and still be able to show the progress bar if the process is lengthy. The existing progress bar was on the UI thread and therefore never updated until the service call completed. Martin has upgraded the progress bar to overcome this limitation.

Within each DocumentViewModel, there is an internal reference counter (held in the AbstractDocumentViewModel) which keeps track of how many things are currently in progress for that document.
When this counter > 0, the progress bar (or spinning busy graphic) is shown on that document.

In order to notify it that something is in progress (usually a service call or something which will take a detectable period of time to complete), within your DocumentViewModel class, you can call :
ProgressBarToggle(true);

And to notify that this action is finished with :
ProgressBarToggle(false);

The method ProgressBarToggle, is threadsafe and may be called on any thread. If it is called on the UI thread in direct response to a UI event such as a button click, then the method will take care of the fact that the UI would normally not update the progress bar visibility until the event handling method was complete & fork the thread to handle outstanding UI messages and binding updates, before continuing on with the functionality of the event handling method. In effect a VB-style “DoEvents” under the covers.

[Note : This has been added to the fledgling developer document in sharepoint :
.../Leisureflexdotnet/Design%2Documents/Forms/AllItems.aspx/“Sandstorm Developer Notes Braindump.docx”]

WCF Fault Exception

Martin had an obscure problem with WCF on our Fitspace / Fitness First Widget.

This article describes a similar issue Obscure WCF Exception mislaid blame

Wednesday, 15 July 2009

Databinding and Nullable Types

In this article (Using WPF Binding StringFormat property with nullable types) Karl Shifflett describes how to bind to properties that have a nullable type.

In summary, use TargetNullValue property of the binding like this:
<TextBox
Text="{Binding Path=NumberOfComputers,
TargetNullValue={x:Static sys:String.Empty},
StringFormat=\{0:D\}}" />

TargetNullValue requires .NET 3.5 Framework Service Pack 1. Previously this would have required a IValueConverter class to deal with the Null values.

Sorting Arrays

Martin pointed me at this interesting blog regarding Array.Sort Sorting Arrays

I used Array.Sort previously in this post Sorting and De-Duping Arrays but didn't investigate further at that time.

A quick look at Array.Sort(...) shows that it has 17 overloads and lots of things to try out at some point in the future.

Tuesday, 14 July 2009

Parameter Ordering

Although the two ComboBox samples below look very similar they actually function a little differently.
The first sample sets the selected item based on the SelectedItem binding and then almost instantaneously sets the SelectedItem based on the first record in the ItemsSource binding.
<ComboBox
DisplayMemberPath="Description"
SelectedItem="{Binding Path=EditedCourse.Centre, Mode=TwoWay}"
SSForm:FormItem.LabelContent="Centre"
IsEditable="{Binding Path=EditedCourse.IsCentreEditable}">
<ComboBox.ItemsSource>
<Binding
Mode="OneWay">
<Binding.Source>
<CollectionViewSource
x:Name="PART_CentresView"
Source="{Binding Source={StaticResource ViewModel}, Path=Centres, Mode=OneWay}" />
</Binding.Source>
</Binding>
</ComboBox.ItemsSource>
</ComboBox>

The second sample sets the selected item based on the SelectedItem binding only and therefore does what I would have expected to happen from the first sample.
<ComboBox
DisplayMemberPath="Description"
SSForm:FormItem.LabelContent="Centre"
IsEditable="{Binding Path=EditedCourse.IsCentreEditable}">
<ComboBox.ItemsSource>
<Binding
Mode="OneWay">
<Binding.Source>
<CollectionViewSource
x:Name="PART_CentresView"
Source="{Binding Source={StaticResource ViewModel}, Path=Centres, Mode=OneWay}" />
</Binding.Source>
</Binding>
</ComboBox.ItemsSource>
<ComboBox.SelectedItem>
<Binding
Path="EditedCourse.Centre"
Mode="TwoWay" />
</ComboBox.SelectedItem>

</ComboBox>

The implication is that the selected item is not necessarily what you would expect it to be.

In the first sample, the final selected item is the first (default) entry in the item source collection, and in the second sample the final selected item is the item bound to in the SelectedItem property.

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.

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.

Thursday, 12 February 2009

Monday, 2 February 2009

Passing an Enum as a CommandParameter

We wanted to pass an Enum as a CommandParameter and struggled to find the right syntax. The final result turned out to be straightforward.
xmlns:Util="clr-namespace:Sandstorm.Documents.FlexBlockBookings.Util


<RadioButton Name="rbPriceByActivity"
Content="By Activity"
Command="{Binding Path=BBChangePricingCommand}"
CommandParameter="{x:static Util:PricingOptions.ByActivity}"/>

Sunday, 1 February 2009

Validation in MVVM

We're following the MVVM pattern and using Josh Smith's example app Using a Viewmodel to provide meaningful Validation Error Messages to implement validation.

When I was in debugger I noticed that some code was executing twice so I traced through the code once the focus left the textbox.

The order of processing was:
[External Code]
ViewModel.Property.Set
OnPropertyChanged
[External Code]
ViewModel.this[propertyName]
But when you add in a FormattingConverter the order becomes:
[External Code]
FormattingConverter.ConvertBack
[External Code]
ViewModel.Property.Set
OnPropertyChanged
[External Code]
ViewModel.Property.Get
[External Code]
FormattingConverter.Convert
[External Code]
ViewModel.this[propertyName]
[External Code]
ViewModel.this[propertyName]
Which means that the validation gets fired twice.

Because we don't want invalid data in our Model we've recently moved the setting of the Model.Property into the ModelView.this[propertyName] method - not ideal but it is the last opportunity where we still have control. Of course the "double-validation" results in the Model.Property being set twice. Not usually a problem but I fear some hidden side-effect somewhere down the line.

Another slight aggravation is that the Convert function is called before the validation and therefore invalid data will fail to convert then we'll attempt the conversion in the validation process (which was the whole point of this exercise).

IsVisibleChanged

I have the following code which is trying to detect that I’ve clicked on a button and my UserControl is now visible, so I want to set focus to a sensible control in that usercontrol.

void UCBBNotes_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
  if ((bool)e.NewValue == true)
  {
     bool a = txtNotes.Focus();
     // a returns false 
     txtNotes.UpdateLayout();
     bool b = txtNotes.Focus();
     // b returns true
  }
}

So, when reacting to certain events such as “IsVisibleChanged”, the event is called before the layout has updated all the child controls. So txtNotes.Focus() fails because txtNotes.IsVisible = False at that point.

This can either be fixed as above by forcing an UpdateLayout by the Dispatcher – which probably isn’t ideal. Or, instead of watching for the usercontrol to become visible, watch for the textbox we want to focus upon to become visible, like this :

void txtNotes_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
  if ((bool)e.NewValue == true)
  {
     txtNotes.Focus();
  }
}

Thursday, 29 January 2009

Sorting and De-duping arrays

I seem to be obsessed with sorting based on the number of posts I've made on the topic.
Sorting a simple string[] is easy using:

string[] recordIds = { "q", "z", "a", "b", "q" };
 
Array.Sort(recordIds);

To stop a third party component from failing we had to ensure that our string[] array contained only unique strings. Sorting and de-duping using LINQ could be done in a single line:

string[] recordIds = { "q", "z", "a", "b", "q" };
 
var sortedUniqueIds = (from id in recordIds orderby id select id).Distinct();
 
int i=0;
foreach (string id in sortedUniqueIds)
{
   recordIds[i++] = id;
}

Microsoft have an excellent LINQ samples page: 101 LINQ Samples

Wednesday, 28 January 2009

Unhandled Exceptions in VS2008

In our solution we have two basic projects: Client and Server, communicating via WCF.

When the Server components throw an exception the Server's WCF layer catches it, wraps it up as a FaultException and rethrows for the Client to catch.

Even though the exception is handled the debugger signals an unhandled exception when running the Server though VS2008.

From the Debug | Exceptions menu option I've turned the exception handling off for that one specific type: System.ServiceModel.FaultException`1

It would appear that disabling this exception affects only the Server project.

Tuesday, 27 January 2009

Sorting Generic Collections - Redux

Using LINQ it turns out to be quite easy to sort a generic Dictionary by either Key or Value.

In these examples a list of sorted keys is returned in the 'keys' variable.

Alternately the LINQ statement can used directly in a foreach loop.

Dictionary<string, string> dict = new Dictionary<string, string>();
...


// Sort by Key
var keys = from key in dict.Keys orderby key ascending select key;


// Sort by Value
var keys = from key in dict.Keys orderby dict[key] ascending select key;


// Sort within foreach(...) by Key
foreach(string aKey in (from key in dict.Keys orderby key ascending select key)){
...
}

Thursday, 22 January 2009

WCF Security and Certificates

It turns out, you can't do Message level authentication without a Certificate involved to identify the server as the server..
and then because I don't have a bona-fide bought and paid for Certificate for my server, it still fails with arcane errors until you add a magic line to the config file on the client saying "trust any old certificate -- we're not fussy!"
On the server config, I needed this line :
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
so I'll need to tweak those values somehow and right now on the client to avoid the "trusted certificate" issue, I needed :
<serviceCertificate> 
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it will be trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certificate authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
Certificate Validation Differences Between HTTPS, SSL over TCP, and SOAP Security
You can use certificates in Windows Communication Foundation (WCF) with message-layer (SOAP) security in addition to transport-layer security (TLS) over HTTP (HTTPS) or TCP. This topic describes differences in the way such certificates are validated.
When using HTTPS to communicate between a client and a service, the certificate that the server authenticates with must support chain trust by default. That is, it must chain to a trusted root certificate authority. No online check is performed to see whether the certificate has been revoked. You can override this behavior by registering a RemoteCertificateValidationCallback callback, as shown in the following code:
ServicePointManager.ServerCertificateValidationCallback +=
new RemoteCertificateValidationCallback(ValidateServerCertificate);
where the signature for ValidateServerCertificate is as follows:
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)