Friday, March 13, 2009

Silverlight2: ComboBox in DataGrid

Friday, March 13, 2009 Posted by Andre Broers
In this sample a will show a combobox item in a datagrid. It is best to update the datagrid component to the latest:



I will create a Lookup table which will only be loaded once for the whole datagrid which is good for performance.

Start with a ProductProvider:




namespace SilverlightApplication2
{
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public int ProductType { get; set; }
}
}




using System.Collections.ObjectModel;

namespace SilverlightApplication2
{
public class ProductProvider
{
public Collection Products
{
get
{
Collection
ReturnProducts = new Collection();
ReturnProducts.Add(new Product() { ProductId = 1, ProductName = "Product1", ProductType = 1 });
ReturnProducts.Add(new Product() { ProductId = 2, ProductName = "Product2", ProductType = 2 });
ReturnProducts.Add(new Product() { ProductId = 3, ProductName = "Product3", ProductType = 3 });
return ReturnProducts;
}
}
}
}


The lookupprovider:




namespace SilverlightApplication2
{
public class Lookup
{
public int LookupId { get; set; }
public string LookupString { get; set; }
}
}




using System.Collections.ObjectModel;

namespace SilverlightApplication2
{
public class LookupProvider
{
private Collection _Lookups;

public LookupProvider()
{
_Lookups = new Collection
();
_Lookups.Add(new Lookup() { LookupId = 1, LookupString = "Type1" });
_Lookups.Add(new Lookup() { LookupId = 2, LookupString = "Type2" });
_Lookups.Add(new Lookup() { LookupId = 3, LookupString = "Type3" });
}

public Collection
Lookups
{
get
{
return _Lookups;
}
}
}

}


ComboBoxText Usercontrol:



<UserControl x:Class="SilverlightApplication2.ComboBoxText"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid x:Name="LayoutRoot">
<TextBlock x:Name="Text">TextBlock>
Grid>
UserControl>




using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication2
{
public partial class ComboBoxText : UserControl
{
public int Id
{
get { return (int)GetValue(IdProperty); }
set { SetValue(IdProperty, value); }
}

public Collection Lookups
{
get { return (Collection
)GetValue(LookupsProperty); }
set { SetValue(LookupsProperty, value); }
}

public static readonly DependencyProperty IdProperty = DependencyProperty.Register("Id", typeof(int), typeof(ComboBoxText), new PropertyMetadata(new PropertyChangedCallback(ListBoxTextChangedCallback)));

public static readonly DependencyProperty LookupsProperty = DependencyProperty.Register("Lookups", typeof(Collection
), typeof(ComboBoxText), null);

private static void ListBoxTextChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ComboBoxText r = d as ComboBoxText;

foreach (Lookup Lookup in r.Lookups)
{
if (Lookup.LookupId == (int)e.NewValue) {
r.Text.Text = Lookup.LookupString;
}
}
}

public ComboBoxText()
{
InitializeComponent();
}
}
}


ComboBox Usercontrol:



<UserControl x:Class="SilverlightApplication2.ComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:my="clr-namespace:SilverlightApplication2" >
<Grid x:Name="LayoutRoot">
<ComboBox x:Name="Combo" SelectionChanged="ComboBox_SelectionChanged">ComboBox>
Grid>
UserControl>




using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication2
{
public partial class ComboBox : UserControl
{
public int Id
{
get { return (int)GetValue(IdProperty); }
set { SetValue(IdProperty, value); }
}

public Collection Lookups
{
get { return (Collection
)GetValue(LookupsProperty); }
set { SetValue(LookupsProperty, value); }
}

public static readonly DependencyProperty IdProperty = DependencyProperty.Register("Id", typeof(int), typeof(ComboBox), new PropertyMetadata(new PropertyChangedCallback(ComboBoxIdChangedCallback)));

public static readonly DependencyProperty LookupsProperty = DependencyProperty.Register("Lookups", typeof(Collection
), typeof(ComboBox), new PropertyMetadata(new PropertyChangedCallback(ComboBoxLookupsChangedCallback)));

private static void ComboBoxIdChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ComboBox r = d as ComboBox;

foreach (Lookup Lookup in r.Lookups)
{
if (Lookup.LookupId == (int)e.NewValue) r.Combo.SelectedItem = Lookup;
}
}

private static void ComboBoxLookupsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ComboBox r = d as ComboBox;

r.Combo.ItemsSource = r.Lookups;
r.Combo.DisplayMemberPath = "LookupString";
}

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (Lookup Lookup in e.AddedItems)
{
Id = Lookup.LookupId;
}
}

public ComboBox()
{
InitializeComponent();
}
}
}


And the page to make it all happen:



<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="SilverlightApplication2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" xmlns:my="clr-namespace:SilverlightApplication2">
<UserControl.Resources>
<my:ProductProvider x:Key="productProvider"/>
<my:LookupProvider x:Key="lookupProvider"/>
UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<data:DataGrid x:Name="TheGrid" AutoGenerateColumns="False" ItemsSource="{Binding Products, Source={StaticResource productProvider}}" >
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="ProductId" Binding="{Binding ProductId}" />
<data:DataGridTextColumn Header="ProductName" Binding="{Binding ProductName}" />
<data:DataGridTemplateColumn Header="Type">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<my:ComboBoxText Id="{Binding ProductType}" Lookups="{Binding Lookups, Source={StaticResource lookupProvider}}" Margin="4" />
DataTemplate>
data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<my:ComboBox Lookups="{Binding Lookups, Source={StaticResource lookupProvider}}" Id="{Binding ProductType, Mode=TwoWay}" >my:ComboBox>
DataTemplate>
data:DataGridTemplateColumn.CellEditingTemplate>
data:DataGridTemplateColumn>
data:DataGrid.Columns>
data:DataGrid>
StackPanel>
Grid>
UserControl>