2

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

もちろん、これにはグリッドを見つける必要があります。SO question WPFの方法でCrimsonXのFindChildを使用して、最初にitemsControl1を見つけ、次にそれを親として使用してtheGridを見つけました。

    Grid FindTheGrid()
    {

            ItemsControl ic = (ItemsControl)this.FindName("itemsControl1");
            Grid theGrid = FindChild<Grid>(ic, "theGrid");

    }

これは、ボタンのクリック イベント ハンドラーから呼び出されたときに機能します。ただし、ic の childrenCount が 0 であるため、MainWindow のコンストラクターから呼び出すと失敗します。

int childrenCount = VisualTreeHelper.GetChildrenCount(theParent);

では、ウィンドウがユーザーに表示される前に、グリッドの行と列のコレクションを設定するにはどうすればよいでしょうか?

4

2 に答える 2

2

WPF は、ItemsControl の項目 (通常は DataTemplate) の「コンテナー」をバックグラウンドで生成しますが、すぐには利用できません。

アイテムがいつ使用可能になるかを知る唯一の方法は、ItemsControl の ItemContainerGenerator プロパティで StatusChanged イベントをサブスクライブすることです。

itemsControl1.ItemContainerGenerator.StatusChanged += ic_GeneratorStatusChanged;

...そして、一度だけ起動する必要があるため、イベントハンドラー内からサブスクライブを解除します。

void ic_GeneratorStatusChanged(object sender, EventArgs e)
{

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

    itemsControl1.ItemContainerGenerator.StatusChanged -= ic_GeneratorStatusChanged;

    // your items are now generated
}

確かにこれは回り道ですが、ItemsControl の項目がビジュアル ツリーに存在することを知る唯一の方法です。

于 2012-01-04T02:47:57.800 に答える
1

RowDefinitionsグリッドの記述に飽きたColumnDefinitionsので、カスタム DependencyProperties をいくつか作成して、グリッド定義で行/列の数を指定できるようにしました。

依存関係プロパティのコードはここにあり、次のように使用されます。

<Grid local:GridHelpers.RowCount="{Binding RowCount}"
      local:GridHelpers.ColumnCount="{Binding ColumnCount}" />

バインディングに関するエラーが発生する場合はtypeof(Grid)、DependencyProperty 定義の を に変更しtypeof(GridHelpers)ます。ヘルパー クラスの最初のバージョンではバインドが許可されておらず、どのバージョンを投稿したか思い出せません。

編集

変更時にUIを正しく更新するなど、私が使用しているコードは次のとおりSomeIntです。SomeIntボタンをクリックすると2と3を切り替えてテストしていました

XAML

<Grid ShowGridLines="True"
      local:GridProperties.ColumnCount="{Binding SomeInt}"
      local:GridProperties.RowCount="{Binding SomeInt}">

    <TextBox Text="Test" Grid.Row="0" Grid.Column="0" />
    <TextBox Text="Test" Grid.Row="0" Grid.Column="1" />
    <TextBox Text="Test" Grid.Row="0" Grid.Column="2" />
    <TextBox Text="Test" Grid.Row="1" Grid.Column="0" />
    <TextBox Text="Test" Grid.Row="1" Grid.Column="1" />
    <TextBox Text="Test" Grid.Row="1" Grid.Column="2" />
    <TextBox Text="Test" Grid.Row="2" Grid.Column="0" />
    <TextBox Text="Test" Grid.Row="2" Grid.Column="1" />
    <TextBox Text="Test" Grid.Row="2" Grid.Column="2" />
</Grid>

依存関係プロパティ

public class GridProperties
{
    #region RowCount Property

    /// <summary>
    /// Adds the specified number of Rows to RowDefinitions. Default Height is Auto
    /// </summary>
    public static readonly DependencyProperty RowCountProperty =
        DependencyProperty.RegisterAttached("RowCount", typeof(int),
        typeof(GridProperties),
        new PropertyMetadata(-1, RowCountChanged));

    // Get
    public static int GetRowCount(DependencyObject obj)
    {
        return (int)obj.GetValue(RowCountProperty);
    }

    // Set
    public static void SetRowCount(DependencyObject obj, int value)
    {
        obj.SetValue(RowCountProperty, value);
    }

    // Change Event - Adds the Rows
    public static void RowCountChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (!(obj is Grid) || (int)e.NewValue < 0)
            return;

        Grid grid = (Grid)obj;
        grid.RowDefinitions.Clear();

        for (int i = 0; i < (int)e.NewValue; i++)
            grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });

        //SetStarRows(grid);
    }

    #endregion

    #region ColumnCount Property

    /// <summary>
    /// Adds the specified number of Columns to ColumnDefinitions. Default Width is Auto
    /// </summary>
    public static readonly DependencyProperty ColumnCountProperty =
        DependencyProperty.RegisterAttached("ColumnCount", typeof(int),
        typeof(GridProperties),
        new PropertyMetadata(-1, ColumnCountChanged));

    // Get
    public static int GetColumnCount(DependencyObject obj)
    {
        return (int)obj.GetValue(ColumnCountProperty);
    }

    // Set
    public static void SetColumnCount(DependencyObject obj, int value)
    {
        obj.SetValue(ColumnCountProperty, value);
    }

    // Change Event - Add the Columns
    public static void ColumnCountChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (!(obj is Grid) || (int)e.NewValue < 0)
            return;

        Grid grid = (Grid)obj;
        grid.ColumnDefinitions.Clear();

        for (int i = 0; i < (int)e.NewValue; i++)
            grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });

        // SetStarColumns(grid);
    }

    #endregion
}

結果

例1 例2

于 2012-01-04T03:17:10.270 に答える