Denis Mochalov Denis Mochalov - 3 years ago 202
C# Question

How generate custom columns for FrameworkElementFactory(typeof(Datagrid))?

I have DataGrid which must have childGrid in RowDetails but i dont know how to create columns for child grid.

At the moment i have child grid with Autogenerated columns that i dont need:

private static bool CopyWork(TextBox textBox)
{
try
{
var match = Regex.Match(textBox.Text, @"^коп раб");
if (match.Success)
{
var copyWorkWindow = new Window()
{
Topmost = true,
WindowStartupLocation = WindowStartupLocation.CenterScreen,
Title = "Копирование документов",
SizeToContent = SizeToContent.WidthAndHeight
};
var documents = new ObservableCollection<CopyWorkDocument>();
var dataGrid = new DataGrid()
{
ItemsSource = documents,
AutoGenerateColumns = false
};

var generateColumn = new Func<string, string, object[], FrameworkElementFactory>((header, bindingItem, items) =>
{
var column = new FrameworkElementFactory(typeof(DataGridTemplateColumn));
column.SetValue(DataGridTemplateColumn.HeaderProperty, header);

var binding1 = new Binding(bindingItem)
{
Mode = BindingMode.TwoWay
};

var elementTextBlock = new FrameworkElementFactory(typeof(TextBlock));
elementTextBlock.SetValue(TextBlock.TextProperty, binding1);
var cellTemplate = new DataTemplate
{
VisualTree = elementTextBlock
};
column.SetValue(DataGridTemplateColumn.CellTemplateProperty, cellTemplate);

if (items != null)
{
var elementComboBox = new FrameworkElementFactory(typeof(ComboBox));
elementComboBox.SetValue(ComboBox.BackgroundProperty, Brushes.White);
elementComboBox.SetValue(ComboBox.ItemsSourceProperty, items);
elementComboBox.SetValue(ComboBox.SelectedItemProperty, binding1);
var cellEditingTemplate = new DataTemplate
{
VisualTree = elementComboBox
};
column.SetValue(DataGridTemplateColumn.CellEditingTemplateProperty, cellEditingTemplate);
}

return column;
});
dataGrid.Columns.Add(new DataGridTextColumn() { Header = "Название документа", Binding = new Binding("Name") });
dataGrid.Columns.Add(new DataGridTextColumn() { Header = "Количество копий", Binding = new Binding("Documentcount") });

var rowDetailsTemplate = new DataTemplate();
var pagesGrid = new FrameworkElementFactory(typeof(DataGrid));
//pagesGrid.SetValue(DataGrid.AutoGenerateColumnsProperty, false);
pagesGrid.SetValue(DataGrid.ItemsSourceProperty, new Binding("Pages"));
rowDetailsTemplate.VisualTree = pagesGrid;
dataGrid.RowDetailsTemplate = rowDetailsTemplate;

copyWorkWindow.Content = dataGrid;
copyWorkWindow.ShowDialog();
var sB = new StringBuilder();
foreach (var document in documents)
{
sB.Append(document).Append(Environment.NewLine);
}
if (sB.Length > 0)
{
textBox.Text = sB.ToString();
}
}
return match.Success;
}
catch (Exception ex)
{
ex.LogAndShow();
return false;
}
}


There is columnGenerator below.

Object class:

private class CopyWorkDocument
{
public string Name { get; set; }
public int Documentcount { get; set; } = 1;
public List<CopyPage> Pages { get; set; } = new List<CopyPage> { new CopyPage() };

public override string ToString()
{
var sB = new StringBuilder().Append(Name);
foreach (var page in Pages)
{
sB.Append(Environment.NewLine).Append(Documentcount).Append("шт (").Append(page).Append(")");
}
return sB.ToString();
}

public class CopyPage
{
public int Pagecount { get; set; } = 1;
public string Pageformat { get; set; } = "A4";
public string Worktype { get; set; } = "печать";
public string Printtype { get; set; } = "односторонняя";
public bool IsColored { get; set; } = false;

public static string[] Worktypes { get => new string[] { "печать", "копирование", "сканирование", "брошюровка", "твердый переплет" }; }
public static string[] Printtypes { get => new string[] { "односторонняя", "двусторонняя" }; }
public static string[] Formats { get => new string[] { "A4", "A3", "A2", "A1" }; }

public override string ToString()
{
var sB = new StringBuilder().Append(Pagecount).Append(" ").Append(Pageformat);
if (IsColored)
{
sB.Append(" цвет");
}
return sB.ToString();
}
}
}


Example for colum generator:

DataGrid.Columns.Add(generateColumn("ColumnName", "ColumnBinding", "ColumnItemsHelper"[]));


First i did this generator for DataGrid (Conrol), but then i rework it for FrameworkElementFactory (This useless details added because of StackOverflow codelimitation post)

mm8 mm8
Answer Source

As stated on MSDN, using the FrameworkElementFactory class is a deprecated way to programmatically create templates: https://msdn.microsoft.com/en-us/library/system.windows.frameworkelementfactory(v=vs.110).aspx.

You could use the System.Windows.Markup.XamlReader.Parse method instead:

StringBuilder sb = new StringBuilder();
sb.Append("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x =\"http://schemas.microsoft.com/winfx/2006/xaml\">");
sb.Append("<DataGrid ItemsSource=\"{Binding Pages}\" AutoGenerateColumns=\"False\">");
sb.Append("<DataGrid.Columns>");
//append for each column:
sb.Append("<DataGridTextColumn Binding=\"{Binding Name}\" Header=\"Name\" />");
sb.Append("</DataGrid.Columns>");
sb.Append("</DataGrid>");
sb.Append("</DataTemplate>");
dataGrid.RowDetailsTemplate = XamlReader.Parse(sb.ToString()) as DataTemplate;
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download