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();
}
}


No comments: