简体   繁体   English

WPF ListView列按比例调整大小时如何避免水平滚动条

[英]How To Avoid Horizontal Scrollbar During Proportional Resize of WPF ListView Columns

Goal: In a WPF Grid, programmatically resize the columns in a child ListView when the window size is changed, maintaining relative column sizes, without ever displaying a horizontal scrollbar. 目标:在WPF网格中,以编程方式在更改窗口大小时调整子ListView中列的大小,从而保持相对列大小,而无需显示水平滚动条。

Currently, the proportional resizing is working very well except that when I reduce the width of the window, I will get a horizontal scrollbar that has only a tiny amount of space it scrolls. 目前,按比例调整大小的效果很好,除了当我减小窗口的宽度时,我将获得一个水平滚动条,该滚动条仅具有很小的滚动空间。 I am wondering if this is due to the Width property not accounting for the graphic dividers between columns?.. or..? 我想知道这是否是由于Width属性没有考虑列之间的图形分隔符吗?

The part that is causing the problem is the last section where I extend the width of the last column to fill the rest of the space. 导致问题的部分是最后一部分,在该部分中,我扩展了最后一列的宽度以填充其余空间。 I don't want to subtract some magic number that I produce from trial & error (which might work to a certain extent). 我不想从反复试验中减去一些我产生的幻数(可能在一定程度上可行)。

..and yes, eventually I will account for the presence (or not) of a vertical scrollbar, but right now I just want to avoid ever seeing a horizontal scrollbar. ..是的,最终我将考虑是否存在垂直滚动条,但是现在我只想避免看到水平滚动条。

Here is the code that resizes the ListView columns: 以下是调整ListView列大小的代码:

LV_FileList.SizeChanged += this.onLV_FileList_SizeChanged;

... ...

/// <summary>
/// Proportionally resize listview columns when listview size changes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void onLV_FileList_SizeChanged(object sender, SizeChangedEventArgs e)
{
    if ((sender is ListView) && 
        (e.PreviousSize.Width > 0))
    {
        double total_width = 0;
        GridViewColumnCollection gvcc = ((GridView)(sender as ListView).View).Columns;
        foreach (GridViewColumn gvc in gvcc)
        {
            gvc.Width = (gvc.Width / e.PreviousSize.Width) * e.NewSize.Width;
            total_width += gvc.Width;
        }

        //Increase width of last column to fit width of listview if integer division made the total width to small
        if (total_width < e.NewSize.Width)
        {
            gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
        }
    }
}

I added a While loop to the problematic section, but it has the unfortunate effect of not working. 我在有问题的部分添加了While循环,但是不幸的是,它无法正常工作。 The ComputedHorizontalScrollBarVisibilityProperty value never changes as the width of the last column is decremented, so it just goes to 0 and throws an invalid value exception for the width of the column. 当最后一列的宽度递减时,ComputedHorizo​​ntalScrollBarVisibilityProperty值永远不会更改,因此它变为0并为该列的宽度引发无效值异常。 I even tried throwing a call to LV_FileList.UpdateLayout() in the loop, thinking that maybe the display of the listview control needs to be refreshed or something before the horizontal scrollbar goes away. 我什至尝试在循环中抛出对LV_FileList.UpdateLayout()的调用,以为可能需要刷新listview控件的显示或在水平滚动条消失之前执行某些操作。 No dice. 没有骰子。

                //Increase width of last column to fit width of listview if integer division made the total width to small
            if (total_width < e.NewSize.Width)
            {
                gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
                while ((Visibility)LV_FileList.GetValue(ScrollViewer.ComputedHorizontalScrollBarVisibilityProperty) == Visibility.Visible)
                {
                    gvcc[gvcc.Count - 1].Width--;
                    //LV_FileList.UpdateLayout();  <-- doesn't help
                }
            }

Setting the HorizontalScrollBarVisibility property to disabled should do it. HorizontalScrollBarVisibility属性设置为disabled即可。

myListView.SetValue(ScrollViewer.HorizontalScrollBarVisibilityProperty,
    ScrollBarVisibility.Disabled);

Or in XAML... 或在XAML中...

<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">

Here's what I ended up with. 这就是我最后得到的。 It handles a vertical scrollbar as well. 它也处理垂直滚动条。 the one drawback I've found so far is that the horizontal scrollbar will sometimes flash briefly while the user is resizing the window. 到目前为止,我发现的一个缺点是,在用户调整窗口大小时,水平滚动条有时会​​短暂闪烁。 If anyone knows a better way, please post! 如果有人知道更好的方法,请发布! Thanks! 谢谢!

        /// <summary>
    /// Proportionally resize listview columns when listview size changes
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void onLV_FileList_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if ((sender is ListView) && 
            (e.PreviousSize.Width > 0))
        {
            double total_width = 0;
            GridViewColumnCollection gvcc = ((GridView)(sender as ListView).View).Columns;
            foreach (GridViewColumn gvc in gvcc)
            {
                gvc.Width = (gvc.Width / e.PreviousSize.Width) * e.NewSize.Width;
                total_width += gvc.Width;
            }

            //Increase width of last column to fit width of listview if integer division made the total width to small
            if (total_width < e.NewSize.Width)
            {
                gvcc[gvcc.Count - 1].Width += (e.NewSize.Width - total_width);
            }

            //Render changes to ListView before checking for horizontal scrollbar
            this.AllowUIToUpdate();

            //Decrease width of last column to eliminate scrollbar if it is displayed now
            ScrollViewer svFileList = this.FindVisualChild<ScrollViewer>(LV_FileList);
            while ((svFileList.ComputedHorizontalScrollBarVisibility != Visibility.Collapsed) &&  (gvcc[gvcc.Count - 1].Width > 1))
            {
                gvcc[gvcc.Count - 1].Width--;
                this.AllowUIToUpdate();
            }
        }
    }


    /// <summary>
    /// Threaded invocation to handle updating UI in resize loop
    /// </summary>
    private void AllowUIToUpdate()
    {
        DispatcherFrame dFrame = new DispatcherFrame();

        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new DispatcherOperationCallback(delegate(object parameter)
        {
            dFrame.Continue = false;
            return null;

        }), null);

        Dispatcher.PushFrame(dFrame);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM