如何获取ListView GridViewColumn来填充网格中的剩余空间?

JCh*_*ian 25 .net wpf listview

我想创建一个ListView,它有两列固定宽度,第三列填充剩余空间.所以像这样:

<ListView>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name" Width="*" />
            <GridViewColumn Header="Age" Width="50" />
            <GridViewColumn Header="Gender" Width="50" />
        </GridView>
    </ListView.View>
</ListView>
Run Code Online (Sandbox Code Playgroud)

问题是我无法找到一种方法来让Name列填充剩余的空间,因为设置宽度*不起作用.看起来有一种方法可以使用值转换器来实现这一点,但似乎应该有一种更简单的方法.与DataGrid控件一样,您可以使用*s 指定列的宽度.

GON*_*ale 39

我试图实现同样的事情但后来决定我希望我的ListView列占用ListView的一定百分比,结果是所有列占用了一部分空间并且所有空间都在ListView中消耗.您可以将其设置为在最后一列中包含您喜欢的任何百分比,以直接实现"在最后一列上填充剩余空间"目标.

我觉得这个方法相当健壮和可靠(即使调整大小!)所以我想可能会分享.

我的ListView中有四列用于此示例.您只需SizeChanged使用以下事件处理程序在ListView中注册事件:

private void ProductsListView_SizeChanged(object sender, SizeChangedEventArgs e)
{
    ListView listView = sender as ListView;
    GridView gView = listView.View as GridView;

    var workingWidth = listView.ActualWidth - SystemParameters.VerticalScrollBarWidth; // take into account vertical scrollbar
    var col1 = 0.50;
    var col2 = 0.20;
    var col3 = 0.15;
    var col4 = 0.15;

    gView.Columns[0].Width = workingWidth*col1;
    gView.Columns[1].Width = workingWidth*col2;
    gView.Columns[2].Width = workingWidth*col3;
    gView.Columns[3].Width = workingWidth*col4;
}
Run Code Online (Sandbox Code Playgroud)

  • 我建议使用`SystemParameters.VerticalScrollBarWidth`而不是硬编码的`35`.一些用户(像我一样)自定义滚动条宽度.地雷可能是70左右:)无论如何,+1都是一个很好的答案 (12认同)

Gar*_*ell 14

在研究类似的问题时遇到了这个问题,我的问题是我希望所有列都是'Auto',期望第一个,这只会填补额外的空间,所以我扩展了GONeale的解决方案.

private void ListView_SizeChanged(object sender, SizeChangedEventArgs e)
{
    ListView _ListView = sender as ListView;
    GridView _GridView = _ListView.View as GridView;
    var _ActualWidth = _ListView.ActualWidth - SystemParameters.VerticalScrollBarWidth;
    for (Int32 i = 1; i < _GridView.Columns.Count; i++)
    {
        _ActualWidth = _ActualWidth - _GridView.Columns[i].ActualWidth;
    }
    _GridView.Columns[0].Width = _ActualWidth;
}
Run Code Online (Sandbox Code Playgroud)

那么XAML就是:

...
<ListView.View>
    <GridView>
        <GridViewColumn Header="Title" />
        <GridViewColumn Header="Artist" Width="Auto" />
        <GridViewColumn Header="Album" Width="Auto" />
        <GridViewColumn Header="Genre" Width="Auto" />
    </GridView>
</ListView.View>
...
Run Code Online (Sandbox Code Playgroud)

此代码也可以更通用地使用,因为列数不是硬编码的,稍微调整一下你可以通过某种逻辑来定义'填充列'.

希望它可以帮助别人:)


Jos*_*osh 7

问题是GridViewColumn的列宽是double,而不是GridLength对象,并且没有适当的转换来处理*.不确定这是否是WPF团队的疏忽.你会认为它会得到支持.

除了转换器,我已经看到了它所做的只是另一种方式是在这里: http://www.ontheblog.net/CMS/Default.aspx?tabid=36&EntryID=37.

两者都是不需要的额外工作.我用ListView和GridView组合找到了其他"怪异"的东西,所以我放弃使用它们.如果我需要一个数据网格,我使用我们许可的第三方,如果我需要一个复杂的ListBox样式菜单,我只使用一个模板化的ListBox.


Pal*_*Due 5

尽管博客仍然存在,但在第一个答案中提到的David Hanson-Greville 的OnTheBlog中的解决方案不再可用。我能够在 Wayback Machine 上找到它,并进行了一些审核,这里是:

诀窍是您在 ListView 上设置 Stretch=true ,它会拉伸没有相同宽度的列。

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace Demo.Extension.Properties
{
    ///
    /// ListViewColumnStretch
    ///
    public class ListViewColumns : DependencyObject
    {
        ///
        /// IsStretched Dependancy property which can be attached to gridview columns.
        ///
        public static readonly DependencyProperty StretchProperty =
            DependencyProperty.RegisterAttached("Stretch",
            typeof(bool),
            typeof(ListViewColumns),
            new UIPropertyMetadata(true, null, OnCoerceStretch));

        ///
        /// Gets the stretch.
        ///
        /// The obj.
        ///
        public static bool GetStretch(DependencyObject obj)
        {
            return (bool)obj.GetValue(StretchProperty);
        }

        ///
        /// Sets the stretch.
        ///
        /// The obj.
        /// if set to true [value].
        public static void SetStretch(DependencyObject obj, bool value)
        {
            obj.SetValue(StretchProperty, value);
        }

        ///
        /// Called when [coerce stretch].
        ///
        ///If this callback seems unfamilar then please read
        /// the great blog post by Paul Jackson found here.
        /// http://compilewith.net/2007/08/wpf-dependency-properties.html
        /// The source.
        /// The value.
        ///
        public static object OnCoerceStretch(DependencyObject source, object value)
        {
            ListView lv = (source as ListView);

            //Ensure we dont have an invalid dependancy object of type ListView.
            if (lv == null)
            {
                throw new ArgumentException("This property may only be used on ListViews");
            }

            //Setup our event handlers for this list view.
            lv.Loaded += new RoutedEventHandler(lv_Loaded);
            lv.SizeChanged += new SizeChangedEventHandler(lv_SizeChanged);
            return value;
        }

        ///
        /// Handles the SizeChanged event of the lv control.
        ///
        /// The source of the event.
        /// The instance containing the event data.
        private static void lv_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            ListView lv = (sender as ListView);
            if (lv.IsLoaded)
            {
                //Set our initial widths.
                SetColumnWidths(lv);
            }
        }

        ///
        /// Handles the Loaded event of the lv control.
        ///
        /// The source of the event.
        /// The instance containing the event data.
        private static void lv_Loaded(object sender, RoutedEventArgs e)
        {
            ListView lv = (sender as ListView);
            //Set our initial widths.
            SetColumnWidths(lv);
        }

        ///
        /// Sets the column widths.
        ///
        private static void SetColumnWidths(ListView listView)
        {
            //Pull the stretch columns fromt the tag property.
            List<GridViewColumn> columns = (listView.Tag as List<GridViewColumn>);
            double specifiedWidth = 0;
            GridView gridView = listView.View as GridView;
            if (gridView != null)
            {
                if (columns == null)
                {
                    //Instance if its our first run.
                    columns = new List<GridViewColumn>();
                    // Get all columns with no width having been set.
                    foreach (GridViewColumn column in gridView.Columns)
                    {
                        if (!(column.Width >= 0))
                        {
                            columns.Add(column);
                        }
                        else
                        {
                            specifiedWidth += column.ActualWidth;
                        }
                    }
                }
                else
                {
                    // Get all columns with no width having been set.
                    foreach (GridViewColumn column in gridView.Columns)
                    {
                        if (!columns.Contains(column))
                        {
                            specifiedWidth += column.ActualWidth;
                        }
                    }
                }

                // Allocate remaining space equally.
                foreach (GridViewColumn column in columns)
                {
                    double newWidth = (listView.ActualWidth - specifiedWidth) / columns.Count;
                    if (newWidth >= 10)
                    {
                        column.Width = newWidth - 10;
                    }
                }

                //Store the columns in the TAG property for later use.
                listView.Tag = columns;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您只需将命名空间添加到 XAML 文件中:

xmlns:Extensions="clr-namespace:Demo.Extension.Properties"
Run Code Online (Sandbox Code Playgroud)

并在您的列表视图中使用它:

<ListView ItemsSource="{Binding Path=Items}" DisplayMemberPath="Name"
                          ScrollViewer.VerticalScrollBarVisibility="Auto"
                          Grid.Column="0" Margin="8" Extensions:ListViewColumns.Stretch="true">
Run Code Online (Sandbox Code Playgroud)

  • 这真是废话。为什么你需要做这么多的代码隐藏来完成这么简单的事情?我对 WPF 中的此类内容越来越感到沮丧 (2认同)