2010-12-23 11 views
9

Quiero crear un control de usuario básico con un estilo mediante programación. En este estilo, quiero agregar un Grid (no hay problema), pero no puedo agregar definiciones de columnas a esta cuadrícula.Crear una cuadrícula en WPF como plantilla programáticamente

Mi código de ejemplo es

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; 

Pero la creación de FrameworkElementFactory con el tipo ColumnDefinitionCollection arrojará una excepción "'ColumnDefinitionCollection' type must derive from FrameworkElement, FrameworkContentElement, or Visual3D."

¿Quién me puede ayudar?

+1

Tal vez considere el uso de 'XamlReader.Load()' que se prefiere sobre 'FrameworkElementFactory' – nan

Respuesta

5

simplemente puede añadir definiciones de columna como esto Código

XAML:

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

C# Código:

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); 

para más cheque here

+0

'añadir' (no ' ass ')))) –

+5

Esto no funciona si desea hacerlo como estilo – wickie79

+0

Las definiciones de columna tienen Ancho, no Altura :) – boski

2
//create grid 
      var grid = new FrameworkElementFactory(typeof(Grid)); 

      // assign template to grid 
      CellControlTemplate.VisualTree = grid; 

      // define grid's rows 
      var r = new FrameworkElementFactory(typeof(RowDefinition)); 
      grid.AppendChild(r); 

      // define grid's columns 
      var c = new FrameworkElementFactory(typeof(ColumnDefinition)); 
      grid.AppendChild(c); 

      c = new FrameworkElementFactory(typeof(ColumnDefinition)); 
      c.SetValue(ColumnDefinition.WidthProperty, GridLength.Auto); 
      grid.AppendChild(c); 

      c = new FrameworkElementFactory(typeof(ColumnDefinition)); 
      c.SetValue(ColumnDefinition.WidthProperty, GridLength.Auto); 
      grid.AppendChild(c); 
12

FrameworkElementFactory tiene alguna lógica personalizada para manejar ColumnDefinitions y RowDefinitions en una cuadrícula. Para esos valores, los trata como niños en el árbol de fábrica, por ejemplo:

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); 
1

Solo tiene que cambiar la última parte de su código. Véase más adelante,

Código original:

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

Nuevo Código:

 mainGrid.AppendChild(c1); 
     mainGrid.AppendChild(c2); 
     mainGrid.AppendChild(c3); 
+1

Siempre es bueno explicar por qué es necesario el cambio. – sharakan

Cuestiones relacionadas