ItemsControl,用于安排具有Gridsplitter功能的项目 [英] Itemscontrol that arrange Items with Gridsplitter-Functionality

查看:79
本文介绍了ItemsControl,用于安排具有Gridsplitter功能的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个可以水平堆叠或垂直堆叠物品的布局.每个项目都应该由分隔符分隔,以便用户可以更改大小(如VisualStudio中的工具箱"容器一样) 这些项目来自模型,因此我需要一个ItemsControl,可以在其中设置ItemsSource.

I need a layout that stacks Items horizontal or vertical. Each Item should be separated by a Splitter, so the User can change the Size (Like the Toolbox Container in VisualStudio) The Items come from a Model, so I need a ItemsControl where I can set the ItemsSource.

我的第一个想法是构建一个从Grid派生的CustomControl.他们使用"OnVisualChildrenChanged"方法在添加新项目时做出反应.然后,我想添加新的Column/Rowdefinitions(取决于它是否应该为水平或垂直).但这是第一个Proplem.当网格设置为IsItemsHost ="true"时,我收到一个错误,提示无法访问DefinitionsCollection ...

My first idea was to build a CustomControl derived from Grid. Their I used the "OnVisualChildrenChanged" Method to react when a new Item is added. Then I wantet to add new Column-/Rowdefinitions (Depending wether it schould be horizontal or vertical). But here was the first Proplem. When the Grid is set to IsItemsHost="true" I get a Error that the DefinitionsCollection is not accessable...

从自定义控件中获取一个CodeSnipped,我试图在其中添加一行.

Heres a CodeSnipped from the custom control, where I tried to add a row.

 private void SetRows()
    {
       this.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto };             
    }

    protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
    {
        base.OnVisualChildrenChanged(visualAdded, visualRemoved);
        SetRows();            
    }

我想我现在找到了解决方案.

I think I found a solution right now.

首先,我创建了一个从ItemsControl派生的CustomControl. 在他的模板中,我添加了一个网格而不插入Itempresenter.现在,我重写OnItemsChange.将项目添加到集合中时,我创建一个FrameworkElement并将DataContext设置为添加的项目,然后将两个Column定义添加到网格,然后将我的项目和一个Gridsplitter添加到网格.效果很好,现在我只需要从ItemsControl中获取ItemTemplate即可在网格中使用它.

First I created a CustomControl that derives from ItemsControl. In his template I add a Grid without inserting a Itempresenter. Now I override OnItemsChange. When a Item is added to the Collection I create a FrameworkElement and set DataContext to the added Item, than I add two Column definition to the Grid and add my Item plus an Gridsplitter to the Grid. This works well, now I only need to get the ItemTemplate from my Itemscontrol to use it in the grid.

当我解决了最后一个问题时,我将添加一个小示例.

When I solved this last issue I will add a small example.

推荐答案

到目前为止,这里有我的解决方案.如果有人有更好的主意,欢迎您.

Heres my Solution so far. If someone has a better idea, you're welcome.

在此处显示CustomControl代码:

Heres the CustomControl Code behind:

public class ResizableItemControl : ItemsControl
{
    public ObservableCollection<FrameworkElement> _gridItems = new ObservableCollection<FrameworkElement>();
    private Grid _grid;

    static ResizableItemControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ResizableItemControl), new FrameworkPropertyMetadata(typeof(ResizableItemControl)));
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        if (this.Template != null)
        {
            _grid = this.Template.FindName("PART_Grid", this) as Grid;
        }

        // Add all existing items to grid
        foreach (var item in Items)
        {
            AddItemToGrid(item);
        }
    }

    /// <summary>
    /// Called when Items in ItemsCollection changing
    /// </summary>
    /// <param name="e"></param>
    protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        base.OnItemsChanged(e);
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                if (Items.Count > 0)
                {
                    //Add Items in Grid when new Items where add
                    var myItem = this.Items[Items.Count - 1];
                    AddItemToGrid(myItem);
                }
                break;
        }


    }

    /// <summary>
    ///  Adds Items to grid plus GridSplitter
    /// </summary>
    /// <param name="myItem"></param>
    private void AddItemToGrid(object myItem)
    {
        var visualItem = this.ItemTemplate.LoadContent() as FrameworkElement;
        if (visualItem != null)
        {
            visualItem.DataContext = myItem;

            if (_grid != null)
            {
                if (_grid.ColumnDefinitions.Count != 0)
                {
                    _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
                    _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
                    var gridSplitter = CreateSplitter();
                    Grid.SetColumn(gridSplitter, _grid.ColumnDefinitions.Count - 2);
                    Grid.SetColumn(visualItem, _grid.ColumnDefinitions.Count - 1);
                    _grid.Children.Add(gridSplitter);
                    _grid.Children.Add(visualItem);

                    //_grid.Children.Add(myTest);
                }
                else
                {
                    _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
                    Grid.SetColumn(visualItem, _grid.ColumnDefinitions.Count - 1);
                    _grid.Children.Add(visualItem);
                }
            }
        }

    }

    private static GridSplitter CreateSplitter()
    {
        var gridSplitter = new GridSplitter() {ResizeDirection = GridResizeDirection.Columns};
        gridSplitter.Width = 5;
        gridSplitter.HorizontalAlignment = HorizontalAlignment.Stretch;
        gridSplitter.Background = new SolidColorBrush(Colors.Black);
        return gridSplitter;
    }
}

通用Xaml:

<Style TargetType="{x:Type controls:ResizableItemControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:ResizableItemControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Hidden">
                        <Grid x:Name="PART_Grid"></Grid>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

以及如何使用它:

            <controls:ResizableItemControl
                ItemsSource="{Binding ElementName=this,Path=Items}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Label
                            Content="{Binding Name}"
                            ToolTip="{Binding Description}"
                            Background="Black"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </controls:ResizableItemControl>

这篇关于ItemsControl,用于安排具有Gridsplitter功能的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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