修改ItemsPanel的网格RowDefinitionCollection [英] Modifying an ItemsPanel's Grid RowDefinitionCollection

查看:202
本文介绍了修改ItemsPanel的网格RowDefinitionCollection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是在Windows MainWindow中没有任何子项的后续构造函数



基于SO问题WPF:安排网格中的集合项的答案,我有以下内容:

 < ItemsControl Name =itemsControl1ItemsSource ={Binding MyItems}> 
< ItemsControl.ItemsPanel>
< ItemsPanelTemplate>
< Grid Name =theGridShowGridLines =True/>
< / ItemsPanelTemplate>
< /ItemsControl.ItemsPanel>
< ItemsControl.ItemContainerStyle>
< Style TargetType ={x:Type FrameworkElement}>
< Setter Property =Grid.RowValue ={Binding RowIndex}/>
< Setter Property =Grid.ColumnValue ={Binding ColumnIndex}/>
< / style>
< /ItemsControl.ItemContainerStyle>
< / ItemsControl>

现在,我想在后面的代码中设置网格的行数和列数:
theGrid.RowDefinitions.Clear();
theGrid.ColumnDefinitions.Clear();

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

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

根据 MattHamilton 的答案,网格可用一次itemsControl1。 ItemContainerGenerator.StatusChanged触发状态为GeneratorStatus.ContainersGenerated。然而,试图从事件处理程序中修改网格引发了无法修改RowDefinitionCollection处于只读状态的异常。



那么,如何在向用户显示窗口之前设置Grid的行和列集合?

编辑 :我正在从itemsControl1.ItemContainerGenerator.StatusChanged事件处理程序修改Grid的属性:

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

itemsControl1.ItemContainerGenerator.StatusChanged - = ItemContainerGeneratorStatusChanged;

SetGridRowsAndColumns(InitialNumberOfRows,InitialMaxNumberOfCols);

请注意,SetGridRowsAndColumns(numberOfRows,numberOfCols)稍后会响应点击按钮。 / p>

解决方案

下面介绍如何在不使用ItemsControl的情况下创建矩阵,注意,

代码:

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

命名空间GridDefs
{
///< summary>
/// MainWindow.xaml的交互逻辑
///< / summary>
public partial class MainWindow:Window
{
public MainWindow()
{
InitializeComponent();

//
this.DataContext = this; //交替使用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)));

退货项目;




public interface IMatrixItem
{
Point Position {get; }
}

//模型,注意 - 它必须实现INotifyPropertyChanged,如果
//您想要将其更改传播到UI
public class Item: IMatrixItem
{
public static Item Create(string text,
Point position)
{
Item item = new Item();

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

退货项目;
}

public string Text
{
get;
私人套餐;
}

公共点位置
{
get;
私人套餐;



public class GridEx
{
public static DependencyProperty DimensionProperty =
DependencyProperty.RegisterAttached(Dimension,
类型(大小),
typeof(GridEx),
新PropertyMetadata(新大小(0,0),
(o,e)=>
{
GridEx.OnDimensionChanged((Grid)o,(Size)e.NewValue);
}));

public static DependencyProperty PositionProperty =
DependencyProperty.RegisterAttached(Position,
typeof(Point),
typeof(GridEx),
新的FrameworkPropertyMetadata新点(-1,-1),
(o,e)=>
{
GridEx.OnPostionChanged((UIElement)o,(Point)e.NewValue);
}));
$ b public static DependencyProperty ItemStyleProperty =
DependencyProperty.RegisterAttached(ItemStyle,$ b $ typeof(Style),
typeof(GridEx));

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

#regionDimension

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

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

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

#endregion

#region职位


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)
其中T:DependencyObject
{
for(DependencyObject parent = VisualTreeHelper.GetParent(当前);
parent!= null;
parent = VisualTreeHelper.GetParent(parent))
{
T result = parent as T;

if(result!= null)
返回结果;
}

返回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

#regionItemStyle

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

#regionItems

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

// template
Style style = GetItemStyle(grid);

foreach(项目中的IMatrixItem项目)
{
控制项目控制=新的控制();

grid.Children.Add(itemControl);

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



$ b 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
}
}

标记:

 < 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 =MainWindowHeight =350Width =525>
< Window.Resources>
< Style TargetType =Controlx:Key =t>
< Setter Property =Template>
< Setter.Value>
< ControlTemplate>
< Button Content ={Binding Text}/>
< / ControlTemplate>
< / Setter>
< / style>

< /Window.Resources>

< Grid local:GridEx.Dimension =3,3
local:GridEx.ItemStyle ={StaticResource t}
local:GridEx.Items ={绑定MyItems}>
< / Grid>
< / Window>


This is a followup for ItemsControl has no children during MainWindow's constructor

Based on the answer to SO question "WPF: arranging collection items in a grid", I have the following:

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

Now, I want to set the number of rows and columns of theGrid in the code behind: 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()); 

As per MattHamilton's answer there, the gird is available once itemsControl1. ItemContainerGenerator.StatusChanged fires with status of GeneratorStatus.ContainersGenerated.

However, trying to modify the grid from the event handler raises an "Cannot modify 'RowDefinitionCollection' in read-only state" exception.

So, how can I set theGrid's row and column collections before the window is shown to the user?

edit: I'm modifying the Grid's properties from itemsControl1.ItemContainerGenerator.StatusChanged event handler:

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

        itemsControl1.ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorStatusChanged;

        SetGridRowsAndColumns(InitialNumberOfRows, InitialMaxNumberOfCols);

Notice that SetGridRowsAndColumns(numberOfRows, numberOfCols) does work later, in a response to a button click.

解决方案

Here's how you can create a matrix without using ItemsControl, note, that you pertain the main thing - the ability to specify templates for the items.

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>

这篇关于修改ItemsPanel的网格RowDefinitionCollection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆