这是ItemsControl has no children during MainWindow's constructor的后续行动
基于对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的行数和列数: 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()); 根据MattHamilton的回答,一旦itemsControl1. ItemContainerGenerator.StatusChanged触发状态为GeneratorStatus.ContainersGenerated,网格就可用了。
但是,试图从事件处理程序修改网格会引发“无法在只读状态下修改'RowDefinitionCollection‘”异常。
那么,在窗口显示给用户之前,如何设置user的行和列集合?
itemsControl1.ItemContainerGenerator.StatusChanged编辑:我正在从事件处理程序修改网格的属性:
if (itemsControl1.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
return;
itemsControl1.ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorStatusChanged;
SetGridRowsAndColumns(InitialNumberOfRows, InitialMaxNumberOfCols);注意,SetGridRowsAndColumns(numberOfRows,numberOfCols)稍后会在单击按钮的响应中工作。
发布于 2012-01-04 13:49:06
我会使用附加行为,而不是对ItemsControl的低级别自定义。
如果您所需要的只是一个矩阵控件--您可以考虑使用行网格而不是ItemsControl (这就是我们最终得到的结果)。ItemsControl是无限强大的创造者,但在某些时候,通过其良好的设计来挤压一个小而有用的额外未来可能是一个挑战。
您必须按照此方法进行的更改如下: 1.使用维度并将其绑定到您希望达到的大小。2.创建一个自定义的ItemTemplate,并将GridEx.Position添加到它的根视觉绑定到relvant属性。
在这两种情况下,给我们一个呼喊,我会更新我的答复与更多的细节。
这是一堂课:
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>发布于 2012-01-04 15:38:00
下面是如何在不使用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>https://stackoverflow.com/questions/8727545
复制相似问题