2017-10-12 212 views
3

我使用Rachel Lim的GridHelper來獲取動態行數。我想要實現的是讓每行都顯示爲一個在另一個之下(完成),以便能夠調整它們的大小(使用GridSplitter完成),並根據屏幕大小調整內容大小。ItemsControl - Grid子元素自動調整大小

結果:

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> 

視圖模型:

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

我不知道我得到的問題提得好,你要的是,默認情況下該行應該有一定的高度,即使有沒有內容。那是什麼需要? –

+0

是的,我希望行的大小按比例調整窗口大小。 @ mm8得到了正確的部分,但調整大小(與GridSplitter)停止正常工作。 –

+0

哦,所以基本上,你希望內容分佈在整個視圖中,當我調整窗口大小時,你還想縮放行和列? –

回答

1

我認爲你的方法是錯的。您不能使用ItemsControl,因爲GridSplitter項目需要位於ItemsPanel級別,而不是DataTemplate - 否則,它將不起作用。

您最好使用對電網本身的自定義行爲 - 見下面的示例代碼:

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> 

我已經測試這和它的工作原理完全一樣。

你需要做的唯一額外的事情是NuGet包Systems.Windows.Interactivity.WPF添加到您的項目

+0

偉大的工作院長!我在哪裏可以深入瞭解更多關於交互性庫的內容? –

+0

這是一個很好的起點https://msdn.microsoft.com/zh-cn/library/dn195669(v=vs.110).aspx –

+0

只是一個可能會讀取此內容的人的小更新:如果您有內部行爲ItemControl(就像我有,但沒有在這個示例中顯示),你必須重寫OnAttached並在其中調用ResetGrid。 protected override void 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); 
} 

和設置您的第一RowDefinition*Height

<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來調整行的大小。 –