【问题标题】:How can I group GridViewColumns in WPF, so the expander fills the whole width如何在 WPF 中对 GridView 列进行分组,以便它们扩展器填充整个宽度
【发布时间】:2019-01-18 11:10:42
【问题描述】:

我是 WPF 新手并尝试执行以下操作:

我有一个使用 ViewModel 的带有 ItemsSource 的 ListView。 在里面,有一个带有列的 GridView。每个 Column 代表 View Model 的一个 Preoperty。但是描述是可选的,可能会很长。所以我想使用扩展器。我的问题是,我只能将扩展器管理为与名称列一样大。但我希望扩展器与整行一样大。 这里有 2 张图片来说明我想要什么。

我现在的状态: https://i.stack.imgur.com/ZNA4v.png

我想要实现的目标: https://i.stack.imgur.com/ZmFq1.png

我尝试“对 GridView 进行分组”,但没有成功...请参见此处 http://technico.qnownow.com/grouping-gridview-wpf/

这是我的代码

<Window ...>
<Window.Resources>
    ...
</Window.Resources>
<DockPanel>
    <StackPanel DockPanel.Dock="Top">
        ...
    </StackPanel>
    <Grid>            
        <ListView Grid.RowSpan="4" DockPanel.Dock="Top" Margin="10" ItemsSource="{Binding MyView}">
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="BorderBrush" Value="Black"></Setter>
                    <Setter Property="BorderThickness" Value="0,0,0,1"></Setter>
                    <Setter Property="Focusable" Value="False" />
                    <Setter Property="HorizontalAlignment" Value="Stretch" />
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="VerticalAlignment" Value="Top"></Setter>
                    <Setter Property="VerticalContentAlignment" Value="Top"></Setter>
                </Style>
            </ListView.ItemContainerStyle>

            <!-- New GridView -->
            <ListView.View>
                <GridView>

                    <!--Number-->
                    <GridViewColumn Header="#">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate DataType="viewModel:MyViewModel">
                                <TextBlock Text="{Binding Model.Number, StringFormat='#{0}', Mode=OneWay}"
                                               Width="20" TextAlignment="Left" Margin="5" VerticalAlignment="Top" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                    <!--ErrorLevel-->
                    <GridViewColumn Header="" Width="45">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate DataType="viewModel:MyViewModel">
                                <Image Source="{Binding Model.ErrorLevel, Converter={StaticResource ErrorLevelToImageConverter}, Mode=OneWay}"
                                           ToolTip="{Binding Model.ErrorLevel, Mode=OneWay}" Width="20" Margin="5" VerticalAlignment="Top" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                    <!--ID-->
                    <GridViewColumn Header="ID">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate DataType="viewModel:MyViewModel">
                                <TextBlock TextAlignment="Center" Margin="5" Width="50" VerticalAlignment="Top" >
                                        <Hyperlink NavigateUri="{Binding Model.Hyperlink, Mode=OneWay}"
                                                   Command="{Binding HyperlinkCommand}">
                                            <TextBlock Text="{Binding Model.Id, Mode=OneWay}" />
                                        </Hyperlink>
                                    </TextBlock>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                    <!--Name-->
                    <GridViewColumn Header="Name" Width="500" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate DataType="viewModel:MyViewModel">
                                <Expander ToolTip="Expand" ExpandDirection="Down" Foreground="Black" VerticalAlignment="Top">
                                    <Expander.Header>
                                        <TextBlock Text="{Binding Model.Name, Mode=OneWay}"
                                               HorizontalAlignment="{Binding HorizontalAlignment, RelativeSource={RelativeSource AncestorType=ContentPresenter}, Mode=OneWayToSource}"
                                               TextAlignment="Left" Margin="5" TextWrapping="Wrap" VerticalAlignment="Top" />
                                    </Expander.Header>
                                    <GroupBox Header="Description" FontWeight="Bold" >
                                        <TextBlock Text="{Binding Model.Description, Mode=OneWay}" TextWrapping="Wrap"
                                                       FontWeight="Normal" TextAlignment="Left" Margin="5" />
                                    </GroupBox>
                                </Expander>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                    <!-- Module-->
                    <GridViewColumn Header="Module" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate DataType="viewModel:MyViewModel">
                                <TextBlock Text="{Binding Model.Module, Mode=OneWay}"
                                               TextAlignment="Center" Margin="5" Width="100" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</DockPanel>

再一次,我是 WPF、MVVM、DataBinding 和所有这些方面的新手。因此,请尽量使您的答案尽可能详细。我尝试了很多东西,但都没有成功。

【问题讨论】:

  • 您想用DataGrid 对条目进行排序(例如按ID 排序)还是没有必要?
  • 嗯,不,我认为它们不需要按特定顺序排列。我目前不使用 DataGrid。这有帮助吗?

标签: c# wpf gridview mvvm expander


【解决方案1】:

您可以在左侧(XAML 中的顶部)将以下 GridViewColumn 添加到您的 GridView

<GridViewColumn Header="" Width="30">
    <GridViewColumn.CellTemplate>
        <DataTemplate DataType="viewModel:MyViewModel">
            <Expander Margin="-5,2,-5000,0" HorizontalAlignment="Left" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}}}">
                <GroupBox Header="Description" FontWeight="Bold" Margin="0,0,5,0">
                    <TextBlock Text="{Binding Model.Description}" FontWeight="Normal" TextWrapping="Wrap" />
                </GroupBox>
            </Expander>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

这是GridViewColumn包含一个空的Header,它只是在GridViewRows 中显示Expander-箭头。

Expander 本身是左对齐的,并且在右侧有一个巨大的负数Margin,因此它可以将其内容绘制到右边界之外。宽度设置为您的GridViewItemsPresenterActualWidth。使用此Width,您可以将内容限制为GridView 的当前可见Width(或者您可以将其设置为绝对值,例如500)。

最后是Column的预览

【讨论】:

  • 哇,这太棒了。您的解决方案完美运行。感谢您的工作和详细的回答。 :-) 编辑:看起来我不能通过评论感谢你......所以我必须添加一个问题。是否可以单击整行来展开描述?现在,只需单击扩展器图像即可。对我来说将是一个不错的功能;-)
  • 我认为感谢永远不会放错地方 :) 您可以使用GridViewRow 的点击事件来执行扩展ExpanderStoryBoard。我建议你看看 MSDN how to animate a Property -> docs.microsoft.com/en-us/dotnet/framework/wpf/…
【解决方案2】:

好的,扩展器不可拉伸的事实是因为不可拉伸的父控件。您的网格视图中有一个“名称”列,宽度固定,扩展器添加为子项。据我所知,如果这不是事实,那么子控件不能超出父控件,我确信有人会纠正这一点。我不知道实现目标的最佳方法是什么,但为了给你一些灵感,我做了一个小例子。

所以,给你一个例子,如果它是如何工作的:

编辑:您可以像这样在扩展器上设置负边距:

<Expander ToolTip="Expand" ExpandDirection="Down" Margin="-100,0,-300,0" Foreground="Black" VerticalAlignment="Top">

感谢@LittleBit 的提示。

<ListView x:Name="lsttest" ItemsSource="{Binding persons}">
        <ListViewItem>
            <StackPanel>
                <ListView>
                    <ListView.View>
                        <GridView>
                            <GridViewColumn Header="#1" Width="50">
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Name}"
                                           Width="20" TextAlignment="Left" Margin="5" VerticalAlignment="Top" />
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                            <GridViewColumn Header="Test 2" Width="50">
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Name}"
                                           Width="20" TextAlignment="Left" Margin="5" VerticalAlignment="Top" />
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                        </GridView>
                    </ListView.View>
                </ListView>
                <Expander ToolTip="Expand" ExpandDirection="Down" Foreground="Black" VerticalAlignment="Top">
                    <Expander.Header>
                        <TextBlock Text="{Binding Model.Name, Mode=OneWay}"
                                           HorizontalAlignment="{Binding HorizontalAlignment, RelativeSource={RelativeSource AncestorType=ContentPresenter}, Mode=OneWayToSource}"
                                           TextAlignment="Left" Margin="5" TextWrapping="Wrap" VerticalAlignment="Top" />
                    </Expander.Header>
                    <GroupBox Header="Description" FontWeight="Bold" Width="{Binding ActualWidth, ElementName=lsttest}">
                        <TextBlock Text="{Binding Name, Mode=OneWay}" TextWrapping="Wrap"
                                                   FontWeight="Normal" TextAlignment="Left" Margin="5" />
                    </GroupBox>
                </Expander>
            </StackPanel>
        </ListViewItem>
        </ListView>

结果:

【讨论】:

  • 一个小提示:负边距有时允许孩子在其边界之外进行渲染/绘制。
  • 非常好,我不知道这在父控件上使用固定宽度是可能的。但我测试了它并且它有效。感谢@LittleBit 的提示。
猜你喜欢
  • 2012-02-06
  • 2021-07-16
  • 2013-05-22
  • 2015-09-21
  • 1970-01-01
  • 2020-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多