ItemsControl - 网格子元素自动调整大小 [英] ItemsControl - Grid child elements auto resize

查看:22
本文介绍了ItemsControl - 网格子元素自动调整大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Rachel Lim 的

我想要的:

Xaml:

<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}"/></风格></ItemsControl.ItemContainerStyle><ItemsControl.ItemTemplate><数据模板><网格><Grid.RowDefinitions><RowDefinition Height="自动"/><RowDefinition Height="自动"/></Grid.RowDefinitions><网格><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions><数据网格><DataGrid.Columns><DataGridTextColumn Header="Col 1"/><DataGridTextColumn Header="Col 2"/><DataGridTextColumn Header="Col 3"/></DataGrid.Columns></DataGrid><Button Grid.Column="1" Content="Btn"/></网格><GridSplitter Height="5" VerticalAlignment="Bottom" Horizo​​ntalAlignment="Stretch" Grid.Row="0" ResizeDirection="Rows" ResizeBehavior="CurrentAndNext"/></网格></数据模板></ItemsControl.ItemTemplate></ItemsControl></网格>

视图模型:

内部类 MyViewModel{公共 ObservableCollection行源{获取;放;}公共 int RowCount { 获取 { 返回 RowSource.Count;} }公共 MyViewModel(){RowSource = new ObservableCollection(){新 RowInfo() { RowNumber = 0 },新 RowInfo() { RowNumber = 1 },新 RowInfo() { RowNumber = 2 }};}}

行信息:

公共类RowInfo{公共 int RowNumber { 获取;内部设置;}}

解决方案

我认为你的方法完全错误.您不能使用 ItemsControl,因为 GridSplitter 项目需要在 ItemsPanel 级别而不是在 DataTemplate- 否则,它将无法工作.

最好在网格本身上使用自定义行为 - 请参阅下面的示例代码:

 公共类 GridAutoRowChildBehavior : Behavior{公共静态只读 DependencyProperty ItemTemplateProperty =DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(GridAutoRowChildBehavior),新的 PropertyMetadata(null, OnGridPropertyChanged));公共静态只读 DependencyProperty ItemsSourceProperty =DependencyProperty.Register("ItemsSource", typeof(object), typeof(GridAutoRowChildBehavior),新的 PropertyMetadata(null, OnGridPropertyChanged));私有静态无效 OnGridPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e){((GridAutoRowChildBehavior) d).ResetGrid();}私有无效重置网格(){var source = ItemsSource 作为 IEnumerable;if (source == null || ItemTemplate == null)返回;AssociatedObject.Children.Clear();AssociatedObject.RowDefinitions.Clear();无功计数 = 0;foreach(源中的 var 项目){var content = 新的 ContentPresenter{内容模板 = 项目模板,内容 = 项目};var splitter = 新的 GridSplitter{高度 = 5,VerticalAlignment = VerticalAlignment.Bottom,Horizo​​ntalAlignment = Horizo​​ntalAlignment.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);计数++;}}公共数据模板 ItemTemplate{得到{返回(数据模板)GetValue(ItemTemplateProperty);}set { SetValue(ItemTemplateProperty, value);}}公共对象 ItemsSource{得到 { 返回 GetValue(ItemsSourceProperty);}设置 { SetValue(ItemsSourceProperty, value);}}}

然后在您的 XAML 中像这样编写代码:

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

我已经对此进行了测试,它完全符合您的需要.

您唯一需要做的就是将 Nuget 包 Systems.Windows.Interactivity.WPF 添加到您的项目

I'm using Rachel Lim's GridHelper to get dynamic number of rows. What I wanted to achieve is to have each row displayed one below another (done), to be able to resize them (done - using GridSplitter) and to have content resized proportionally to the screen size.

Result:

What I would like to have:

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

解决方案

I think your approach is all wrong. You cannot use an ItemsControl, as the GridSplitter items need to be at the ItemsPanel level rather than in the DataTemplate - otherwise, it won't work.

You are better off using a custom behavior on the Grid Itself - see example code below:

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

Then in your XAML you code it up like this:

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

I have tested this and it works exactly as you need.

The only additional thing you need to do is add the Nuget package Systems.Windows.Interactivity.WPF to your project

这篇关于ItemsControl - 网格子元素自动调整大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆