Reputation: 5420
if i have such a List let's call it Rows
and i wan't to add like myDataGrid.ItemsSource = Rows;
than i get in all Columns the first myClass per subList
it looks like
Column0 | Column1 | Column2 | Column3
firstrow0 | firstrow0 | firstrow0 | firstrow0
firstrow1 | firstrow1 | firstrow1 | firstrow1
firstrow2 | firstrow2 | firstrow2 | firstrow2
<DataGrid Name="myDataGrid" AutoGenerateColumns="False">
<DataGrid.Columns >
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type vmv:myClass}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type vmv:myClass}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type vmv:myClass}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
var list = new List<List<myClass>>();
for (int row = 0; row < 3; row++)
{
var myRow = new List<myClass>();
for (int col = 0; col < 5; col++)
myRow.Add(new myClass() { ID = col, Name = "Row"+row +" Column:" + col });
list.Add(myRow);
}
myDataGrid.ItemsSource = list.AsEnumerable<IEnumerable>();
public class myClass
{
public int ID { get; set; }
public string Name { get; set; }
// other stuff
}
What do i need to get this working. Do i need to cast it in some way? Do i need some other Object
as a List<>
?
Anything that could help is greatly appreciated!
in RL Code i will not be able to change the DataTemplate part
because it part of XAMLFile
that will created by my company so it will fit so parameters but original it will only be for printing. I only load it to Find("ItemTemplate")
=> cast it as DataTemplate
and us it to provide a WYSIWYG
for the DataGridCell
because the Width and Height will be different from PrintTemplate
to PrintTemplate
the following code is the solution for my specific Problem take also a look at michele Answer
#region example Datacreation
var list = new List<IEnumerable>();
for (int row = 0; row < 5; row++)
{
var myRow = new List<myClass>();
for (int col = 0; col < 5; col++)
{
myRow.Add(new myClass() { ID = col, Name = "Row" + row + " Column:" + col });
}
list.Add(myRow);
}
#endregion
#region FileToDataTemplate
var myXamlFile = "<Window xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' "
+ "xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' "
+ "xmlns:vmv='clr-namespace:toDataGrid;assembly=toDataGrid' " //namespace
+ "SizeToContent='WidthAndHeight'>"
+ "<Window.Resources>"
+ "<DataTemplate x:Name='myFileCellTemplate' DataType='{x:Type vmv:myClass}'>"
+ "<TextBlock Text='{Binding Name}'/>"
+ "</DataTemplate>"
+ "</Window.Resources>"
// some stuff
+ "</Window>";
Window myWindow = (Window)XamlReader.Load(XmlReader.Create(new StringReader(myXamlFile)));
myWindow.Close();
DataTemplate myCellTemplate = (DataTemplate)myWindow.FindName("myFileCellTemplate");
#endregion
DataGrid myDataGrid = new DataGrid();
#region dyn DataGridcreation
for (int col = 0; col < 5; col++)
{
#region HelperDataTemplatecreation
var myResourceDictionaryString = "<ResourceDictionary xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' "
+ "xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' "
+ "xmlns:vmv='clr-namespace:toDataGrid;assembly=toDataGrid'>" //namespace
+ "<DataTemplate DataType='{x:Type vmv:myClass}'>"
+ "<Label Content='{Binding [" + col + "]}'/>"
+ "</DataTemplate>"
+ "</ResourceDictionary> ";
ResourceDictionary ResDic = (ResourceDictionary)XamlReader.Load(XmlReader.Create(new StringReader(myResourceDictionaryString)));
DataTemplate HelpDTemp = (DataTemplate)ResDic[ResDic.Keys.Cast<Object>().First()];
#endregion
DataGridTemplateColumn templateColumn = new DataGridTemplateColumn();
templateColumn.Header = col;
templateColumn.CellTemplate = HelpDTemp;
templateColumn.CellEditingTemplate = HelpDTemp;
myDataGrid.Columns.Add(templateColumn);
}
#endregion
myDataGrid.Resources.Add(new DataTemplateKey(typeof(myClass)), myCellTemplate);
myDataGrid.ItemsSource = list.AsEnumerable<IEnumerable>();
Upvotes: 1
Views: 796
Reputation: 2091
In your shoes I will generate all the DataGridColumns programmatically (as suggested in the comments) so you can assign the correct DataContext to every cell and everything will be really dynamic.
But, if your question it's only about a DataBinding
problem, your example will work if you change your TextBlock DataBinding expression to:
<TextBlock Text="{Binding [0].Name}"/>
for the first data template, [1].Name
and [2].Name
for the other two DataTemplates.
That's will work beacuse your row DataContext is a List<T>
, so adding [#]
to your DataBinding expression will set the data context of every cell to the correct object.
EDIT - Based on comments below: How to create datagridcolumn programmatically using a given datattemplate from resources.
In code behind
//In your example you have 5 columns
for (int c = 0; c < 5; c++)
{
DataGridTemplateColumn column = new DataGridTemplateColumn();
//Basically i will wrap your DataTemplate in a ContentPresenter
//The ContentProperty is set to point to the correct element of your list
var factory = new FrameworkElementFactory(typeof(ContentPresenter));
factory.SetBinding(ContentPresenter.ContentProperty, new Binding(string.Format("[{0}]", c.ToString())));
factory.SetValue(ContentPresenter.ContentTemplateProperty, this.FindResource("YourTemplateName") as DataTemplate);
column.SetValue(DataGridTemplateColumn.CellTemplateProperty, new DataTemplate { VisualTree = factory });
myDataGrid.Columns.Add(column);
}
Upvotes: 1