When attempting to use a ComboBox in the CellEditingTemplate of a column of a Silverlight4 DataGrid, the binding expression for ItemsSource is not resolving correctly.
The RIA DomainDataSource I wish to use is called installerGroupDomainDataSource and the following XAML works fine at page level. The list is populated and when I bind the Text property of a TextBlock to the combobox's SelectedValue, the value of Id shows that the whole shenanigans is working as advertised.
<ComboBox
ItemsSource="{Binding ElementName=installerGroupDomainDataSource, Path=Data}"
DisplayMemberPath="Caption" SelectedValuePath="Id" Name="foo" />
The same XAML conspicuously fails to work when it is hosted in a CellEditingTemplate in a DataGrid column definition, like this:
<sdk:DataGridTemplateColumn x:Name="installerGroupIdColumn"
Header="Installer Group" Width="SizeToHeader">
but the CellTemplate text block does show the value of Id.
Implementing simDataGrid_PreparingCellForEdit with a breakpoint allowed inspection of the combobox at run-time, revealing that ItemsSource was null.
All of this leads me to conclude that I need to specify binding expressions somewhat differently. ElementName does not seem to resolve correctly when the combobox is in a template.
Can anyone advise, and save me a great deal of trial and error?
Aha! MSDN has this to say:
Styles and templates in WPF provide the ability to reuse and reapply content in a straightforward way, but styles and templates might also include elements with names defined at the template level. That same template might be used multiple times in a page. For this reason, styles and templates both define their own XAML namescopes, independent of the containing page where the style or template is applied.
...
If you are working from within a template, and need to get to the XAML namescope where the template is applied, get the value of TemplatedParent, and then call FindName there.
I wish I knew how to use this information.
Dan Wahlin also appears to have answers, but I can't get his DataContextProxy to work, because a dot-notated path doesn't seem to work in my XAML.
If I use simDataGrid_PreparingCellForEdit to set the ItemsSource, the list appears correctly but there seem to be other binding woes.
I have discovered that both DataGrid and DataForm impose namescopes that are disjunct to the page namescope. As a result the ElementName binding notation cannot resolve elements defined in the page. Page resources are accessible using the StaticResource notation, and so the solution is to declare the DDSs as page resources and bind to them like this
<navigation:Page.Resources>
<riaControls:DomainDataSource x:Key="billingGroupDDS"
d:DesignData="{d:DesignInstance my1:BillingGroup, CreateList=true}"
LoadedData="billingGroupDomainDataSource_LoadedData"
Name="billingGroupDomainDataSource"
QueryName="GetBillingGroupsQuery" Margin="0,0,640,201">
<riaControls:DomainDataSource.DomainContext>
<my2:GpsoDomainContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
<riaControls:DomainDataSource x:Key="installerGroupDDS"
d:DesignData="{d:DesignInstance my1:InstallerGroup, CreateList=true}"
LoadedData="installerGroupDomainDataSource_LoadedData"
Name="installerGroupDomainDataSource"
QueryName="GetInstallerGroupsQuery" Margin="0,0,640,201">
<riaControls:DomainDataSource.DomainContext>
<my2:GpsoDomainContext />
</riaControls:DomainDataSource.DomainContext>
</riaControls:DomainDataSource>
</navigation:Page.Resources>
...
<sdk:DataGridTemplateColumn x:Name="billingGroupIdColumn"
Header="Billing Group" Width="SizeToHeader">
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox
Name="cbxBillingGroup"
ItemsSource="{Binding Data,Source={StaticResource billingGroupDDS}}"
DisplayMemberPath="Caption"
SelectedValuePath="Id"
SelectedValue="{Binding BillingGroupId}">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding BillingGroupId}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>