Friday 17 October 2008

Silverlight DataGrid as Properties Window

Today I needed to use the Silverlight DataGrid control as a Visual Studio-like properties window - basically showing a list of Key/Value pairs and allowing editing of the value via a suitable control. At the moment our properties are only of type string or bool so the control required was either a TextBox or a CheckBox depending on the type of the value.

Firstly I set the AutoGenerateColumns property on the grid to True in the hope that it might be clever enough to realise what I was trying to do and render the grid appropriately. Not surprisingly the value column was built as a DataGridTextColumn and all the bool values shown as their ToString().

Eventually I came up with using a DataGridTemplateColumn containing each type of control we needed in the DataTemplate, binding the Visibility property to the value and using a converter to decide whether or not the control should be visible depending on the type of the value.

The XAML for the grid ended up like this:


<controls:DataGrid x:Name="properties" Grid.Row="3" AutoGenerateColumns="False" >
<controls:DataGrid.Columns>
<controls:DataGridTextColumn Header="Name" IsReadOnly="True" Binding="{Binding Name, Mode=OneTime}"/>
<controls:DataGridTemplateColumn Header="Value">
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<TextBox Text="{Binding Value, Mode=TwoWay}" Background="Transparent" BorderBrush="Transparent" Visibility="{Binding Value, Converter={StaticResource ValueVisibilityConverter}, ConverterParameter='String'}"/>
<CheckBox IsChecked="{Binding Value, Mode=TwoWay}" Background="Transparent" Visibility="{Binding Value, Converter={StaticResource ValueVisibilityConverter}, ConverterParameter='Boolean'}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumn>
</controls:DataGrid.Columns>
</controls:DataGrid>


It uses the following IValueConverter implementation to convert the value into a Visibility value - the parameter is the data type that the control will show ie. String, Boolean so we should be able to easily add more controls as our types of property increase.



public class ValueVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility result = Visibility.Collapsed;
if(value != null)
{
if (value.GetType().Name == parameter.ToString())
{
result = Visibility.Visible;
}
}

return result;
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}


Friday 10 October 2008

LINQ to Entities LIKE Operator

A couple of weeks ago I was asked to move some search functionality that had been prototyped in LINQ to SQL into production code for which we are using the Entity Framework and LINQ to Entities.

One of the main requirements of the search was that we have the ability to query any text column in the search table using any combination of wildcard the user liked. The LINQ to SQL prototype used the SqlMethods.Like method but as this is only available in the SQL implementation of LINQ another method was required. A search around the internet basically said that there is no LIKE operator in LINQ to Entities but the StartsWith(), EndsWith() and Contains() methods on the string class can give the functionality of '%smith', '%smith%' and 'smith%' but I couldn't find a solution that would allow us to use wildcards as per the requirements.

I eventually decided that I'd try and write an extension method on IQueryable that would provide this functionality - while looking into how to go about this I found a Where() method on System.Data.Objects.ObjectQuery which takes a parameter of string and a list of parameters. It turned out that this allowed us to provide a predicate using Entity SQL and, as ObjectQuery implements IQueryable the result can be used as part of a LINQ to Entities query as well.

So our search query could look something like this:

EntityContainer.Customers.Where("It.Surname like '%sm%i%th%' and It.Forename like 'j%o%h'");

Obviously this doesn't give us the type safety of a LINQ implementation in the predicate but is certainly useful for search functionality.

Saturday 4 October 2008

The First Post

Hello!

So what do you write in your first post? The obvious answer being whatever you like because no-one will be reading it!

Basically, recently I've been doing a lot of work using Silverlight, WCF, LINQ and the Entity Framework and while there are a lot of resources around there are still things that I've needed to do that, when searching online, I have found very little about. Therefore I figured when I solve an issue that has little or no mention anywhere why not blog about it myself and maybe help others that have the same problem. For instance I'll post about a LIKE operator in LINQ to Entities soon which was a problem with a simple solution that I only found more complicated solutions to.

Shortly I'll also be starting to develop a cricket scoring application that will, hopefully, be used to score league cricket matches here in the UK as I think this needs to be made easier to do so that more people are able to score the game. When I get going with this project I'll also share some of my thoughts on how I will be putting that together.