2012-01-04 4 views
0

d'un ItemsPanel Ceci est un suivi pour ItemsControl has no children during MainWindow's constructorLa modification de grille RowDefinitionCollection

Sur la base de la réponse à la question SO "WPF: organiser des objets de collection dans une grille", je donne les résultats suivants:

<ItemsControl Name="itemsControl1" ItemsSource="{Binding MyItems}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Grid Name="theGrid" ShowGridLines="True" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemContainerStyle> 
     <Style TargetType="{x:Type FrameworkElement}"> 
      <Setter Property="Grid.Row" Value="{Binding RowIndex}" /> 
      <Setter Property="Grid.Column" Value="{Binding ColumnIndex}" /> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
</ItemsControl> 

Maintenant, Je veux définir le nombre de lignes et de colonnes de Grid dans le code derrière: theGrid.RowDefinitions.Clear(); theGrid.ColumnDefinitions.Clear();

 for (uint i = 0; i < theNumberOfRows; i++) 
      theGrid.RowDefinitions.Add(new RowDefinition()); 

     for (uint i = 0; i < theNumberOfCols; i++) 
      theGrid.ColumnDefinitions.Add(new ColumnDefinition()); 

Comme par MattHamilton « s réponse là, le ceindre est disponible une fois itemsControl1. ItemContainerGenerator.StatusChanged se déclenche avec l'état GeneratorStatus.ContainersGenerated. Toutefois, essayer de modifier la grille à partir du gestionnaire d'événements déclenche une exception «Impossible de modifier 'RowDefinitionCollection' en lecture seule». Alors, comment puis-je définir les collections de lignes et de colonnes de theGrid avant que la fenêtre ne s'affiche à l'utilisateur?

modifier: Je modifier les propriétés de la grille du gestionnaire d'événements itemsControl1.ItemContainerGenerator.StatusChanged:

 if (itemsControl1.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) 
      return; 

     itemsControl1.ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorStatusChanged; 

     SetGridRowsAndColumns(InitialNumberOfRows, InitialMaxNumberOfCols); 

Notez que SetGridRowsAndColumns (numberOfRows, numberOfCols) ne fonctionne plus tard, en réponse à un bouton clic .

+0

Salut Avi, où modifiez vous exactement votre grille en ligne/Col de Defs? –

+0

Salut Dmitry. Ajout d'une modification expliquant ceci. – Avi

Répondre

0

J'utiliserais un comportement joint plutôt qu'une personnalisation de bas niveau pour ItemsControl.

Si tout ce dont vous avez besoin est un contrôle matriciel - vous pourriez envisager d'utiliser une grille de lignes au lieu de ItemsControl (c'est ce que nous avons fini avec). ItemsControl est un creaturem puissant et illimité, mais il peut être un peu difficile de presser un futur petit mais utile grâce à son design sonore. Les modifications que vous aurez à effectuer en suivant cette approche sont les suivantes: 1. Utilisez Dimension et liez-le à une Taille que vous voulez. 2. Créez un ItemTemplate personnalisé et ajoutez GridEx.Position à son visuel racine lié à la propriété Relvant Point. Sur ces deux, donnez-nous un cri et je mettrai à jour ma réponse avec plus de détails.

est ici la classe:

public class GridEx 
    { 
     public static DependencyProperty DimensionProperty = 
      DependencyProperty.Register("Dimension", 
      typeof(Size), 
      typeof(Grid), 
      new PropertyMetadata((o, e) => 
      { 
       GridEx.OnDimensionChanged((Grid)o, (Size)e.NewValue); 
      })); 

     public static DependencyProperty PositionProperty = 
      DependencyProperty.Register("Position", 
      typeof(Point), 
      typeof(UIElement), 
      new PropertyMetadata((o, e) => 
      { 
       GridEx.OnPostionChanged((UIElement)o, (Point)e.NewValue); 
      })); 

     private static void OnDimensionChanged(Grid grid, Size resolution) 
     { 
      grid.RowDefinitions.Clear(); 
      grid.ColumnDefinitions.Clear(); 

      for (int i = 0; i < resolution.Width; i++) 
      { 
       grid.ColumnDefinitions.Add(new ColumnDefinition()); 
      } 

      for (int i = 0; i < resolution.Height; i++) 
      { 
       grid.RowDefinitions.Add(new RowDefinition()); 
      } 
     } 

     private static void OnPostionChanged(UIElement item, Point position) 
     { 
      Grid.SetColumn(item, Convert.ToInt32((position.X))); 
      Grid.SetRow(item, Convert.ToInt32(position.Y)); 
     } 

     public static void SetDimension(Grid grid, Size dimension) 
     { 
      grid.SetValue(GridEx.DimensionProperty, dimension); 
     } 

     public static Size GetDimension(Grid grid) 
     { 
      return (Size)grid.GetValue(GridEx.DimensionProperty); 
     } 

     public static void SetPosition(UIElement item, Point position) 
     { 
      item.SetValue(GridEx.PositionProperty, position); 
     } 

     public static Point GetPosition(Grid grid) 
     { 
      return (Point)grid.GetValue(GridEx.PositionProperty); 
     } 
    } 

Et voici comment nous les utilisons:

<Window x:Class="GridDefs.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:GridDefs" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid local:GridEx.Dimension="3,3"> 
     <Button local:GridEx.Position="0,0">A</Button> 
     <Button local:GridEx.Position="1,1">A</Button> 
     <Button local:GridEx.Position="2,2">A</Button> 
    </Grid> 
</Window> 
0

Voici comment vous pouvez créer une matrice sans utiliser ItemsControl, note, que vous appartenez la chose principale - la possibilité de spécifier des modèles pour les éléments.

code:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace GridDefs 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      // 
      this.DataContext = this; // alterantively use RelativeSource 
     } 

     public IEnumerable<Item> MyItems 
     { 
      get 
      { 
       List<Item> items = new List<Item>(3); 

       items.Add(Item.Create("A1", new Point(0, 0))); 
       items.Add(Item.Create("B2", new Point(1, 1))); 
       items.Add(Item.Create("C3", new Point(2, 2))); 

       return items; 
      } 
     } 
    } 

    public interface IMatrixItem 
    { 
     Point Position { get; } 
    } 

    // Model, note - it has to implement INotifyPropertyChanged if 
    // you want to propagate its changes up to the UI 
    public class Item: IMatrixItem 
    { 
     public static Item Create(string text, 
      Point position) 
     { 
      Item item = new Item(); 

      item.Text = text; 
      item.Position = position; 

      return item; 
     } 

     public string Text 
     { 
      get; 
      private set; 
     } 

     public Point Position 
     { 
      get; 
      private set; 
     } 
    } 

    public class GridEx 
    { 
     public static DependencyProperty DimensionProperty = 
      DependencyProperty.RegisterAttached("Dimension", 
      typeof(Size), 
      typeof(GridEx), 
      new PropertyMetadata(new Size(0, 0), 
       (o, e) => 
       { 
        GridEx.OnDimensionChanged((Grid)o, (Size)e.NewValue); 
       })); 

     public static DependencyProperty PositionProperty = 
      DependencyProperty.RegisterAttached("Position", 
      typeof(Point), 
      typeof(GridEx), 
      new FrameworkPropertyMetadata(new Point(-1, -1), 
       (o, e) => 
       { 
        GridEx.OnPostionChanged((UIElement)o, (Point)e.NewValue); 
       })); 

     public static DependencyProperty ItemStyleProperty = 
      DependencyProperty.RegisterAttached("ItemStyle", 
      typeof(Style), 
      typeof(GridEx)); 

     public static DependencyProperty ItemsProperty = 
      DependencyProperty.RegisterAttached("Items", 
      typeof(IEnumerable<IMatrixItem>), 
      typeof(GridEx), 
      new PropertyMetadata((o, e) => 
      { 
       GridEx.OnItemsChanged((Grid)o, (IEnumerable<IMatrixItem>)e.NewValue); 
      })); 

     #region "Dimension" 

     private static void OnDimensionChanged(Grid grid, Size resolution) 
     { 
      grid.RowDefinitions.Clear(); 
      grid.ColumnDefinitions.Clear(); 

      for (int i = 0; i < resolution.Width; i++) 
      { 
       grid.ColumnDefinitions.Add(new ColumnDefinition()); 
      } 

      for (int i = 0; i < resolution.Height; i++) 
      { 
       grid.RowDefinitions.Add(new RowDefinition()); 
      } 
     } 

     public static void SetDimension(Grid grid, Size dimension) 
     { 
      grid.SetValue(GridEx.DimensionProperty, dimension); 
     } 

     public static Size GetDimension(Grid grid) 
     { 
      return (Size)grid.GetValue(GridEx.DimensionProperty); 
     } 

     #endregion 

     #region "Position" 


     private static void OnPostionChanged(UIElement item, Point position) 
     { 
      item.SetValue(Grid.ColumnProperty, Convert.ToInt32(position.X)); 
      item.SetValue(Grid.RowProperty, Convert.ToInt32(position.Y)); 
     } 

     private static T GetParentOfType<T>(DependencyObject current) 
      where T : DependencyObject 
     { 
      for (DependencyObject parent = VisualTreeHelper.GetParent(current); 
       parent != null; 
       parent = VisualTreeHelper.GetParent(parent)) 
      { 
       T result = parent as T; 

       if (result != null) 
        return result; 
      } 

      return null; 
     } 

     public static void SetPosition(UIElement item, Point position) 
     { 
      item.SetValue(GridEx.PositionProperty, position); 
     } 

     public static Point GetPosition(UIElement grid) 
     { 
      return (Point)grid.GetValue(GridEx.PositionProperty); 
     } 

     #endregion 

     #region "ItemStyle" 

     public static void SetItemStyle(Grid item, Style style) 
     { 
      item.SetValue(GridEx.ItemStyleProperty, style); 
     } 

     public static Style GetItemStyle(Grid grid) 
     { 
      return (Style)grid.GetValue(GridEx.ItemStyleProperty); 
     } 

     #endregion 

     #region "Items" 

     private static void OnItemsChanged(Grid grid, IEnumerable<IMatrixItem> items) 
     { 
      grid.Children.Clear(); 

      // template 
      Style style = GetItemStyle(grid); 

      foreach (IMatrixItem item in items) 
      { 
       Control itemControl = new Control(); 

       grid.Children.Add(itemControl); 

       itemControl.Style = style; 
       itemControl.DataContext = item; 

      } 
     } 

     public static void SetItems(Grid grid, IEnumerable<IMatrixItem> items) 
     { 
      grid.SetValue(GridEx.ItemsProperty, items); 
     } 

     public static IEnumerable<IMatrixItem> GetItems(Grid grid) 
     { 
      return (IEnumerable<IMatrixItem>)grid.GetValue(GridEx.ItemsProperty); 
     } 

     #endregion 
    } 
} 

Markup:

<Window x:Class="GridDefs.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:GridDefs" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <Style TargetType="Control" x:Key="t"> 
      <Setter Property="local:GridEx.Position" Value="{Binding Position}"></Setter> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate> 
         <Button Content="{Binding Text}" /> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

    </Window.Resources> 

    <Grid local:GridEx.Dimension="3,3" 
      local:GridEx.ItemStyle="{StaticResource t}" 
      local:GridEx.Items="{Binding MyItems}"> 
    </Grid> 
</Window> 
Questions connexes