Is there a way to modify DataTemplate
before returning it in DataTemplateSelector
?
My DataTemplate
is defined in XAML. There is an element in this template that I need to set binding for, but whose binding path will only be decided at run-time. The template looks like this:
<DataTemplate DataType="vm:FormField">
<StackPanel>
<ComboBox ItemsSource="{Binding ValueList.DefaultView}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Mode=OneWay}" /> <!--This is the problem child-->
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</DataTemplate>
TextBlock.Text
needs to set its binding path to a property that will be supplied by the underlying data item. My DataTemplateSelector
uses the following code to assign it the new path:
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
//MultiValueTemplate is the above template
var Content = MultiValueTemplate.LoadContent() as StackPanel;
var ComboItemText = (Content.Children[0] as ComboBox).ItemTemplate.LoadContent() as TextBlock;
//Underlying item contains the field name that I want this to bind to.
ComboItemText.SetBinding(TextBlock.TextProperty, (item as MyItemVM).FieldName);
return MultiValueTemplate;
}
This doesn't work. Code runs, but the output doesn't set TextProperty
binding. What do I need to change/add?
Note: I have solved this problem using FrameworkElementFactory
approach, but I have had to redefine the entire DataTemplate
in the code (which is a pain even for simple template like the one above). I want to use the one that I have already defined in XAML.
Note 2: FrameworkElementFactory
approach assigns the constructed template object to DataTemplate.VisualTree
in the last step, just before returning. I think it is that part that I'm missing, but there is no way of doing that since VisualTree
asks for an object of FrameworkElementFactory
type, which we do not have when using XAML-based template.
We are basically getting JSON structure from the server-side that looks something like this:
`[
"Person":
{
"Name": "Peter",
"Score": 53000
},
"Person":
{
"Name": "dotNET",
"Score": 24000
}
,...
]
What fields will be included in JSON will be determined by the server. Our application is required to parse this JSON and then display as many ComboBoxes as there are fields. Each ComboBox will then list down one field in it. So in the above example, there will be one combo for Names and one for Scores. User can choose an option either from the first or second ComboBox, but selecting from one combo will automatically select corresponding item from the other combo(s).
Now you may ask, who the hell designed this idiotic UI? Unfortunately we neither know nor control this decision. I ask the client to instead use ONE Combo (instead of many) with a DataGrid as its dropdown, so that we could display one data item per grid row and user could choose one of those items. Clear and Simple. But the management didn't agree and here we are trying to mimic synchronized comboboxes. LOL.
So what we're currently doing is to transform incoming JSON to a DataTable
on-the-fly. This DataTable gets one column for each JSON field and as many row as their are items; kind of pivoting you can say. We then create ComboBoes and bind each one to a single field of this DataTable. This field name is of course dynamic and is decided at run-time, which mean that I have to modify the DataTemplate
at run-time, which brings up this question.
Hope it didn't get too boring! :)
look like you can bind SelectedValuePath
and DisplayMemberPath
to FieldName and be done with that:
<ComboBox SelectedValuePath="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=DataContext.FieldName}"
DisplayMemberPath="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=DataContext.FieldName}"/>