具有ItemsControl的网格中的Gridsplitter [英] Gridsplitter in a Grid with an ItemsControl

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

问题描述

我正在尝试制作PropertyGrid自定义控件。 PropertyGrid将与Visual Studio中使用的PropertyGrid非常相似。我尝试使用扩展WPF工具包的PropertyGrid,但是您必须使用属性指定属性的类别,并且我们需要更改类别运行时。据我所知,属性是不可能的。

I'm trying to make a PropertyGrid Custom Control. The PropertyGrid will be very similar to the PropertyGrid used in Visual Studio. I've tried using the PropertyGrid of the Extended WPF Toolkit but you have to specify the category of a property with an attribute and we need to change the categories runtime. Which as far as I know is impossible with attributes.

所以我要自己制作PropertyGrid。到目前为止,这是我的代码:

So I'm making the PropertyGrid myself. This is my code so far:

Generic.xaml:

The Generic.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:HomeMadePropertyGrid"
                    xmlns:System="clr-namespace:System;assembly=mscorlib">

    <BooleanToVisibilityConverter x:Key="BoolToVisConverter"></BooleanToVisibilityConverter>
    <SolidColorBrush x:Key="GlyphBrush" Color="#444" />
    <ControlTemplate x:Key="toggleButtonTemplate" TargetType="ToggleButton">
        <Grid Width="15" Height="13" Background="Transparent">
            <Path x:Name="ExpandPath" Fill="{StaticResource GlyphBrush}" Data="M 4 0 L 8 4 L 4 8 Z" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1,1,1,1" />
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsChecked" Value="True">
                <Setter Property="Data" TargetName="ExpandPath" Value="M 0 4 L 8 4 L 4 8 Z"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <Style x:Key="toggleButtonStyle" TargetType="ToggleButton">
        <Setter Property="Template" Value="{StaticResource toggleButtonTemplate}" />
    </Style>

    <Style TargetType="{x:Type local:PropertyGrid}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:PropertyGrid}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <ItemsControl ItemsSource="{TemplateBinding ItemsSource}">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <VirtualizingStackPanel/>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel Background="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}">
                                        <StackPanel Orientation="Horizontal">
                                            <ToggleButton x:Name="toggleButton" Height="20" Width="20" Style="{StaticResource toggleButtonStyle}"/>
                                            <TextBlock Text="{Binding Name}" FontWeight="Bold"></TextBlock>
                                        </StackPanel>
                                        <ItemsControl ItemsSource="{Binding Items}">
                                            <ItemsControl.ItemTemplate>
                                                <DataTemplate>
                                                    <Grid Visibility="{Binding ElementName=toggleButton, Path=IsChecked, Converter={StaticResource BoolToVisConverter}}" 
                                                          Grid.IsSharedSizeScope="True">

                                                        <Grid.ColumnDefinitions>
                                                            <ColumnDefinition Width="*"/>
                                                            <ColumnDefinition Width="Auto" />
                                                            <ColumnDefinition Width="*"/>
                                                        </Grid.ColumnDefinitions>

                                                        <Border BorderThickness="1" BorderBrush="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}">
                                                            <TextBlock Background="White" Text="{Binding Path=Name}"/>
                                                        </Border>
                                                        <GridSplitter Width="1" 
                                                                      Grid.RowSpan="4" Grid.Column="1" 
                                                                      HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                                                                      Background="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}"/>
                                                        <Border Grid.Column="2" BorderThickness="1" BorderBrush="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}">
                                                            <ContentPresenter Grid.Column="2" Content="{Binding Value}">
                                                                <ContentPresenter.Resources>
                                                                    <DataTemplate DataType="{x:Type System:String}">
                                                                        <TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}" 
                                                                             BorderThickness="0"/>
                                                                    </DataTemplate>
                                                                    <DataTemplate DataType="{x:Type System:Int32}">
                                                                        <TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}" 
                                                                             TextAlignment="Right"
                                                                             BorderThickness="0"/>
                                                                    </DataTemplate>
                                                                    <DataTemplate DataType="{x:Type System:Double}">
                                                                        <TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}" 
                                                                             TextAlignment="Right"
                                                                             BorderThickness="0"/>
                                                                    </DataTemplate>
                                                                    <DataTemplate DataType="{x:Type System:Boolean}">
                                                                        <CheckBox IsChecked="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
                                                                                  HorizontalAlignment="Center"/>
                                                                    </DataTemplate>
                                                                </ContentPresenter.Resources>
                                                            </ContentPresenter>
                                                        </Border>
                                                    </Grid>
                                                </DataTemplate>
                                            </ItemsControl.ItemTemplate>
                                        </ItemsControl>
                                    </StackPanel>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

PropertyGrid.cs

PropertyGrid.cs

public class PropertyGrid : ItemsControl
{
    public Brush GridColor
    {
        get { return (Brush)GetValue(GridColorProperty); }
        set { SetValue(GridColorProperty, value); }
    }

    public static readonly DependencyProperty GridColorProperty =
        DependencyProperty.Register("GridColor", typeof(Brush), typeof(PropertyGrid), new UIPropertyMetadata(new SolidColorBrush(Colors.Transparent)));

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

PropertyGroup

PropertyGroup

public class PropertyGroup
{
    public string Name { get; set; }
    public List<PropertyGridItem> Items { get; set; }

    public PropertyGroup()
    {
        Items = new List<PropertyGridItem>();
        Name = "";
    }
}

PropertyGridItem

PropertyGridItem

public class PropertyGridItem
{
    public string Name { get; set; }
    public object Value { get; set; }

    public PropertyGridItem(string propertyName, object propertyValue)
    {
        Name = propertyName;
        Value = propertyValue;
    }
}

此代码在我的MainWindow.xaml中:

This code in my MainWindow.xaml:

<local:PropertyGrid ItemsSource="{Binding Path=Groups}" GridColor="#f0f0f0"/>

我的ViewModel的代码背后:

Code behind of my ViewModel:

public MainWindow()
{
    InitializeComponent();
    this.DataContext = new ViewModel();
}

ViewModel

The ViewModel

public class ViewModel
{
    public List<PropertyGroup> Groups { get; set; }

    public ViewModel()
    {
        Groups = new List<PropertyGroup>();

        PropertyGroup group1 = new PropertyGroup();
        group1.Name = "Group1";
        group1.Items.Add(new PropertyGridItem("Item1", "test"));
        group1.Items.Add(new PropertyGridItem("Item2", 300));
        group1.Items.Add(new PropertyGridItem("Item3", true));
        group1.Items.Add(new PropertyGridItem("Item4", 5.2));
        Groups.Add(group1);

        PropertyGroup group2 = new PropertyGroup();
        group2.Name = "Group2";
        group2.Items.Add(new PropertyGridItem("Item1", "test"));
        group2.Items.Add(new PropertyGridItem("Item2", 300));
        group2.Items.Add(new PropertyGridItem("Item3", true));
        group2.Items.Add(new PropertyGridItem("Item4", 5.2));
        Groups.Add(group2);
    }
}

我遇到的问题是GridSplitter是应用于每一行。我希望将GridSplitter应用于组的所有行。我知道这是因为我为每个项目都创建了一个新的网格。为了使附加属性起作用,这些项目必须是Grid的直接子级。
也不能选择DataGrid,因为GridSplitter仅在列标题之间可用。

The problem I'm having is that the GridSplitter is applied every row. I want the GridSplitter to be applied to all rows of a group. I understand that this is because I make a new Grid for every item. For the attached properties to work the items have to be a direct child of the Grid. A DataGrid also isn't an option because the GridSplitter is only available between column headers.

因此,总而言之:我如何在ItemsControl中使用带有GridSplitter的网格,该网格理想地适用于组的所有行,或者整个网格

So to make a long story short: how can I use a Grid in an ItemsControl with a GridSplitter that applies to all rows of ideally a group or the entire Grid if that isn't possible.

推荐答案

我终于找到了解决此问题的方法。

I finally found the solution to this problem.

要使其正常工作,我必须:

To get this to work I had to:


  • 设置网格。

  • 使用任意名称在名称列上设置SharedSizeGroup属性。

  • 删除名称上的星形大小柱。由于某些原因,第一列和第三列都具有星形大小会导致GridSplitter卡住。

  • 在GridSplitter上设置固定宽度,我将Width设置为2。

  • 将GridSplitter的ResizeBehaviour设置为PreviousAndNext。

  • Set the Grid.IsSharedSizeScope to true on the parent ItemsControl.
  • Set the SharedSizeGroup property on the name column with an arbitrary name.
  • Remove the star sizing on the name column. Having both the first and third column with star sizing resulted in a stuck GridSplitter for some reason.
  • Set a fixed width on the GridSplitter, I set the Width to 2.
  • Set the ResizeBehaviour of the GridSplitter to PreviousAndNext.

以下是所得代码的相关部分:

Here is a relevant piece of the resulting code:

 <ItemsControl ItemsSource="{Binding Items}" Grid.IsSharedSizeScope="True">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
                <Grid Visibility="{Binding ElementName=toggleButton, Path=IsChecked, Converter={StaticResource BoolToVisConverter}}" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" SharedSizeGroup="nameColumn"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Border Grid.Column="0"  Style="{StaticResource BodyPropertyGrid_CellBorder}">
                    <TextBlock Text="{Binding Path=Name}"/>
                </Border>
                <GridSplitter Grid.Column="1" Width="2"
                              ResizeBehavior="PreviousAndNext"
                              Style="{StaticResource BodyPropertyGridSplitter}"/>
                <Border Grid.Column="2" Style="{StaticResource BodyPropertyGrid_CellBorder}">
                    <ContentControl Content="{Binding}" 
                                    ContentTemplateSelector="{StaticResource propertyItemTemplateSelector}"/>
                </Border>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

这篇关于具有ItemsControl的网格中的Gridsplitter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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