2017-10-12 4 views
3

私はRachel LimのGridHelperを使用して動的な行数を取得しています。私が目指していたのは、各行を別の行の下に表示させ(完了)、サイズを変更し(GridSplitterを使用して)、画面サイズに比例してサイズを変更できるようにすることでした。ItemsControl - グリッドの子要素自動サイズ変更

結果:私が持っているしたいと思い何

enter image description here

enter image description here

XAML:

<Grid> 
    <ItemsControl ItemsSource="{Binding RowSource}" > 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <Grid local:GridHelper.RowCount="{Binding RowCount}" /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemContainerStyle> 
      <Style TargetType="ContentPresenter"> 
       <Setter Property="Grid.Row" Value="{Binding RowNumber}"/> 
      </Style> 
     </ItemsControl.ItemContainerStyle> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition Height="Auto"/> 
        </Grid.RowDefinitions> 
        <Grid> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="*" /> 
          <ColumnDefinition Width="Auto" /> 
         </Grid.ColumnDefinitions> 
         <DataGrid> 
          <DataGrid.Columns> 
           <DataGridTextColumn Header="Col 1" /> 
           <DataGridTextColumn Header="Col 2" /> 
           <DataGridTextColumn Header="Col 3" /> 
          </DataGrid.Columns> 
         </DataGrid> 
         <Button Grid.Column="1" Content="Btn" /> 
        </Grid> 
        <GridSplitter Height="5" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Grid.Row="0" ResizeDirection="Rows" ResizeBehavior="CurrentAndNext"/> 
       </Grid> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Grid> 

のViewModel:

internal class MyViewModel 
{ 
    public ObservableCollection<RowInfo> RowSource { get; set; } 

    public int RowCount { get { return RowSource.Count; } } 

    public MyViewModel() 
    { 
     RowSource = new ObservableCollection<RowInfo>() 
     { 
      new RowInfo() { RowNumber = 0 }, 
      new RowInfo() { RowNumber = 1 }, 
      new RowInfo() { RowNumber = 2 } 
     }; 
    } 
} 

RowInfo:

public class RowInfo 
{ 
    public int RowNumber { get; internal set; } 
} 
+0

にNugetパッケージSystems.Windows.Interactivity.WPFを追加することですその中には内容がありません。それが必要なのでしょうか? –

+0

はい、ウィンドウのサイズに比例して行のサイズを変更したいです。 @ mm8はその部分を正しく持っていましたが、(GridSplitterを使って)サイズ変更が正しく動作するのをやめました。 –

+0

ああ、基本的には、全体のビューにコンテンツを広げたいのですが、ウィンドウのサイズを変更すると、行と列も同様に拡大したいのですか? –

答えて

1

あなたのアプローチはすべて間違っていると思います。 ItemsControlを使用することはできません。GridSplitterのアイテムは、DataTemplateではなく、ItemsPanelのレベルである必要があります。そうでないと機能しません。

あなたはグリッド自体にカスタム動作を使用したほうが良いです - 下記のコード例を参照してください。

public class GridAutoRowChildBehavior : Behavior<Grid> 
{ 
    public static readonly DependencyProperty ItemTemplateProperty = 
     DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(GridAutoRowChildBehavior), 
      new PropertyMetadata(null, OnGridPropertyChanged)); 

    public static readonly DependencyProperty ItemsSourceProperty = 
     DependencyProperty.Register("ItemsSource", typeof(object), typeof(GridAutoRowChildBehavior), 
      new PropertyMetadata(null, OnGridPropertyChanged)); 

    private static void OnGridPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((GridAutoRowChildBehavior) d).ResetGrid(); 
    } 

    private void ResetGrid() 
    { 
     var source = ItemsSource as IEnumerable; 
     if (source == null || ItemTemplate == null) 
      return; 
     AssociatedObject.Children.Clear(); 
     AssociatedObject.RowDefinitions.Clear(); 
     var count = 0; 
     foreach (var item in source) 
     { 
      var content = new ContentPresenter 
      { 
       ContentTemplate = ItemTemplate, 
       Content = item 
      }; 
      var splitter = new GridSplitter 
      { 
       Height = 5, 
       VerticalAlignment = VerticalAlignment.Bottom, 
       HorizontalAlignment = HorizontalAlignment.Stretch 
      }; 
      AssociatedObject.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); 
      Grid.SetRow(content,count); 
      Grid.SetRow(splitter,count); 
      AssociatedObject.Children.Add(content); 
      AssociatedObject.Children.Add(splitter); 
      count++; 
     } 

    } 

    public DataTemplate ItemTemplate 
    { 
     get { return (DataTemplate) GetValue(ItemTemplateProperty); } 
     set { SetValue(ItemTemplateProperty, value); } 
    } 


    public object ItemsSource 
    { 
     get { return GetValue(ItemsSourceProperty); } 
     set { SetValue(ItemsSourceProperty, value); } 
    } 
} 

を次に、あなたのXAMLであなたはこのようにそれをコード:

<Grid> 
    <i:Interaction.Behaviors> 
     <local:GridAutoRowChildBehavior ItemsSource="{Binding RowsSource}"> 
      <local:GridAutoRowChildBehavior.ItemTemplate> 
       <DataTemplate> 
        <Grid> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="*" /> 
          <ColumnDefinition Width="Auto" /> 
         </Grid.ColumnDefinitions> 
         <DataGrid> 
          <DataGrid.Columns> 
           <DataGridTextColumn Header="Col 1" /> 
           <DataGridTextColumn Header="Col 2" /> 
           <DataGridTextColumn Header="Col 3" /> 
          </DataGrid.Columns> 
         </DataGrid> 
         <Button Grid.Column="1" Content="Btn" /> 
        </Grid> 
       </DataTemplate> 
      </local:GridAutoRowChildBehavior.ItemTemplate> 
     </local:GridAutoRowChildBehavior> 
    </i:Interaction.Behaviors> 
</Grid> 

私がテストしていますこれは必要なだけ正確に動作します。

あなたがする必要がある唯一の追加の事は何をしたいことは、デフォルトでは行があってもそこにいくつかの高さを持つべきであるということです、私はよく質問を取得することを確認していないプロジェクト

+0

すばらしい仕事ディーン!インタラクティビティライブラリの詳細はどこで読むことができますか? –

+0

これは良い出発点ですhttps://msdn.microsoft.com/en-us/library/dn195669(v=vs.110).aspx –

+0

これを読んでいる人のためのちょっとした更新です。Behavior inside ItemControl(私は持っているが、このサンプルには表示されていない)では、OnAttachedをオーバーライドし、その内部でResetGridを呼び出す必要があります。 protected override override OnAttached() { base.OnAttached(); ResetGrid(); } また、AssociatedObjectがResetGridメソッド内でnullであるかどうかを確認します。 –

1

使用スターサイジングあなたはGridHelperクラスで作成しRowDefintionsのために:

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 = new GridLength(1, GridUnitType.Star) }); //<-- 

    SetStarRows(grid); 
} 

そして*にあなたの最初のRowDefinitionHeightを設定します。

<ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <Grid Background="Yellow"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="*"/> 
       <RowDefinition Height="Auto"/> 
      </Grid.RowDefinitions> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*" /> 
        <ColumnDefinition Width="Auto" /> 
       </Grid.ColumnDefinitions> 
       <DataGrid> 
        <DataGrid.Columns> 
         <DataGridTextColumn Header="Col 1" /> 
         <DataGridTextColumn Header="Col 2" /> 
         <DataGridTextColumn Header="Col 3" /> 
        </DataGrid.Columns> 
       </DataGrid> 
       <Button Grid.Column="1" Content="Btn" /> 
      </Grid> 
      <GridSplitter Height="5" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Grid.Row="0" ResizeDirection="Rows" ResizeBehavior="CurrentAndNext"/> 
     </Grid> 
    </DataTemplate> 
</ItemsControl.ItemTemplate> 
+0

コンテンツサイズに比例してサイズ変更されますが、サイズ変更は正しく機能しません。 –

+0

'サイズ変更 'はどういう意味ですか? – Iron

+0

GridSplitterを使用して行のサイズを変更したいと考えています。 –

関連する問題