I need to use a DataTemplate for my cells in a DataGrid. I'm creating the columns dynamially.
Itemsource of the DataGrid is a ObservableCollection:
class EmployeeRota : BaseViewModel
{
private Employee _employee;
public Employee employee
{
get { return _employee; }
set { _employee = value;
OnPropertyChanged(nameof(employee));
}
}
private ObservableCollection<Shift> _ListOfShifts;
public ObservableCollection<Shift> ListOfShifts
{
get { return _ListOfShifts; }
set { _ListOfShifts = value;
OnPropertyChanged(nameof(ListOfShifts));
}
}
}
The creation of the columns happes dynamically because the ListOfShifts property could contain 1 to x entrys
//Name-column
DataGridTextColumn NameColumn = new DataGridTextColumn() { Header = "Name" };
Binding NamebindingExpression = new Binding($"employee.Name") { Mode = BindingMode.OneWay };
NameColumn.Binding = NamebindingExpression;
grdRota.Columns.Add(NameColumn);
//columns for the shifts depending on ListOfShift count
DataTemplate template = (DataTemplate)grdRota.FindResource("template");
int MaxColumn = vm.ListOfEmployeeRotas.Max(x => x.ListOfShifts.Count);
for (int i = 0; i < MaxColumn; i++)
{
DataGridTemplateColumn column = new DataGridTemplateColumn() { Header = vm.StartDate.AddDays(i).ToShortDateString(), CellTemplate = template };
grdRota.Columns.Add(column);
}
The template is easy as could be:
<DataTemplate x:Key="template">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="10"/>
</StackPanel>
</DataTemplate>
Would I use DataGridTextColumn instead of the DataGridTemplateColumn I could bind to the column and everything would be ok. But DataGridTemplateColumn has no Binding-Property.
So conclusion: Every column needs to be created dynamically and bound to the accordingly index of the ListOfShifts. Also it would be great if there would be a possibility to create the columns dynamically without working in code behind.
You need to create a specific template with a unique binding path for each column.
The key to solve this is to create the templates programmatically using the XamlReader.Parse
method, eg:
const string Xaml = "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" +
"<StackPanel Orientation=\"Horizontal\">" +
"<TextBlock Text=\"{{Binding {0}}}\" Margin=\"10\"/>" +
"</StackPanel>" +
"</DataTemplate>";
for (int i = 0; i < MaxColumn; i++)
{
string bindingPath = $"[{i}].Name";
DataGridTemplateColumn column = new DataGridTemplateColumn()
{
Header = vm.StartDate.AddDays(i).ToShortDateString(),
CellTemplate = XamlReader.Parse(string.Format(Xaml, bindingPath)) as DataTemplate
};
grdRota.Columns.Add(column);
}
I am afraid there is no support for doing this, ie replace the binding path in a template dynamically, in XAML.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.