Создайте сетку в WPF как шаблон программно

Я хочу программно создать базовый пользовательский элемент управления со стилем. В этом стиле я хочу добавить Grid (нет проблем), но я не могу добавить определения столбцов в эту сетку.

Мой пример кода

ControlTemplate templ = new ControlTemplate();
FrameworkElementFactory mainPanel = new FrameworkElementFactory(typeof(DockPanel));
mainPanel.SetValue(DockPanel.LastChildFillProperty, true);

FrameworkElementFactory headerPanel = new FrameworkElementFactory(typeof(StackPanel));
headerPanel.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
headerPanel.SetValue(DockPanel.DockProperty, Dock.Top);
mainPanel.AppendChild(headerPanel);

FrameworkElementFactory headerImg = new FrameworkElementFactory(typeof(Image));
headerImg.SetValue(Image.MarginProperty, new Thickness(5));
headerImg.SetValue(Image.HeightProperty, 32d);
headerImg.SetBinding(Image.SourceProperty, new Binding("ElementImage") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
headerPanel.AppendChild(headerImg);

FrameworkElementFactory headerTitle = new FrameworkElementFactory(typeof(TextBlock));
headerTitle.SetValue(TextBlock.FontSizeProperty, 16d);
headerTitle.SetValue(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center);
headerTitle.SetBinding(TextBlock.TextProperty, new Binding("Title") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
headerPanel.AppendChild(headerTitle);

FrameworkElementFactory mainGrid = new FrameworkElementFactory(typeof(Grid));
FrameworkElementFactory c1 = new FrameworkElementFactory(typeof(ColumnDefinition));
c1.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Star));
FrameworkElementFactory c2 = new FrameworkElementFactory(typeof(ColumnDefinition));
c2.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Auto));
FrameworkElementFactory c3 = new FrameworkElementFactory(typeof(ColumnDefinition));
c3.SetValue(ColumnDefinition.WidthProperty, new GridLength(3, GridUnitType.Star));
FrameworkElementFactory colDefinitions = new FrameworkElementFactory(typeof(ColumnDefinitionCollection));
colDefinitions.AppendChild(c1);
colDefinitions.AppendChild(c2);
colDefinitions.AppendChild(c3);
mainGrid.AppendChild(colDefinitions);

mainPanel.AppendChild(mainGrid);

FrameworkElementFactory content = new FrameworkElementFactory(typeof(ContentPresenter));
content.SetBinding(ContentPresenter.ContentProperty, new Binding() { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent), Path = new PropertyPath("Content") });
mainGrid.AppendChild(content);

templ.VisualTree = mainPanel;
Style mainStyle = new Style();
mainStyle.Setters.Add(new Setter(UserControl.TemplateProperty, templ));
this.Style = mainStyle;

Но создание FrameworkElementFactory с типом ColumnDefinitionCollection вызовет исключение "'ColumnDefinitionCollection' type must derive from FrameworkElement, FrameworkContentElement, or Visual3D."

Кто может мне помочь?


person wickie79    schedule 23.12.2010    source источник
comment
Возможно, рассмотрите возможность использования XamlReader.Load(), это предпочтительнее, чем FrameworkElementFactory   -  person nan    schedule 23.12.2010


Ответы (3)


FrameworkElementFactory имеет некоторую пользовательскую логику для обработки ColumnDefinitions и RowDefinitions в сетке. Для этих значений вы рассматриваете их как дочерние элементы в дереве фабрики, например:

FrameworkElementFactory gridFactory = new FrameworkElementFactory(typeof(Grid));

var column1 = new FrameworkElementFactory(typeof(ColumnDefinition));
column1.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Auto));

var column2 = new FrameworkElementFactory(typeof(ColumnDefinition));
column2.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Star));

gridFactory.AppendChild(column1);
gridFactory.AppendChild(column2);
person Pavan    schedule 25.10.2011

вы можете просто добавить определения столбцов, подобные этому

Код XAML:

<Grid.ColumnDefinitions>
<ColumnDefinition Height="50"/>
<ColumnDefinition Height="100"/>
<ColumnDefinition Height="*"/>
</Grid.ColumnDefinitions>

Код C#:

ColumnDefinition c = new ColumnDefinition();
c.Width = new GridLength(50, GridUnitType.Pixel);

ColumnDefinition c1 = new ColumnDefinition();
c1.Width = new GridLength(100, GridUnitType.Pixel);

ColumnDefinition c2 = new ColumnDefinition();
c2.Width = new GridLength(0, GridUnitType.Star);

grMain.ColumnDefinitions.Add(c);
grMain.ColumnDefinitions.Add(c1);
grMain.ColumnDefinitions.Add(c2);

подробнее см. здесь

person biju    schedule 23.12.2010
comment
Определения столбцов получили ширину, а не высоту :) - person boski; 12.05.2016

Вам просто нужно изменить последнюю часть кода. Смотри ниже,

Оригинальный код:

        colDefinitions.AppendChild(c1);
        colDefinitions.AppendChild(c2);
        colDefinitions.AppendChild(c3);
        mainGrid.AppendChild(colDefinitions);

Новый код:

        mainGrid.AppendChild(c1);
        mainGrid.AppendChild(c2);
        mainGrid.AppendChild(c3);
person Rubin    schedule 31.01.2013
comment
Всегда приятно объяснить, почему необходимы изменения! - person sharakan; 31.01.2013