修改项目面板的网格行定义集合



这是继ItemsControl在MainWindow的构造函数中没有子节点

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

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

现在,我想在后面的代码中设置网格的行数和列数: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()); 

根据matthhamilton的回答,网格一旦itemsControl1可用。ItemContainerGenerator。StatusChanged触发状态为GeneratorStatus.ContainersGenerated。

但是,尝试从事件处理程序修改网格会引发"无法在只读状态下修改'RowDefinitionCollection' "异常。

那么,我如何在窗口显示给用户之前设置网格的行和列集合呢?

edit:我正在从itemsControl1.ItemContainerGenerator修改网格的属性。StatusChanged事件处理程序:

        if (itemsControl1.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
            return;
        itemsControl1.ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorStatusChanged;
        SetGridRowsAndColumns(InitialNumberOfRows, InitialMaxNumberOfCols);

请注意,SetGridRowsAndColumns(numberOfRows, numberOfCols)稍后会在响应按钮单击时起作用。

我会使用附加行为,而不是ItemsControl的低级定制。

如果所有你需要的是一个矩阵控件-你可能会考虑使用行网格而不是ItemsControl(这就是我们最终的结果)。ItemsControl是一个无限强大的生物,但有时它可能是一个挑战,通过它的声音设计挤压一个小而有用的额外未来。

按照这种方法你需要做的改变是:1. 使用尺寸并将其绑定到您想要的大小。2. 创建自定义ItemTemplate并添加GridEx。位置到它的根视觉绑定到相关的Point属性

关于这两个问题,请告诉我们,我会用更多的细节更新我的答案。

这是类:

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

我们是这样使用它的:

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

下面是如何在不使用ItemsControl的情况下创建矩阵的方法,注意,您涉及的主要内容-为项目指定模板的能力。

代码:

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

标记:

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

相关内容

  • 没有找到相关文章

最新更新