【问题标题】:How to resize WPF Listview proportionally?如何按比例调整 WPF Listview 的大小?
【发布时间】:2011-09-14 09:35:51
【问题描述】:

我在调整 Listview 控件的大小时遇到​​了一点问题。我打算让它根据窗口的实际大小按比例调整大小。

对于 Listview 的初始大小,它是 300 X 600(宽 X 高)以像素为单位。我还将它的 ma​​xHeight 设置为 750,但它的宽度保持不变,即 300。

此外,在 Wondow 的属性中,我已将 SizeToContent 属性更改为 WidthAndHeight,正如一些线程建议的那样,您可以让系统决定控件的正确大小调整窗口大小后。

但是,它还没有工作。所以我在这里寻求帮助。谢谢。

附:无论如何我们可以在WPF中设置宽度和高度的百分比值吗?如果允许我使用百分比,例如高度 = 80%,那会容易得多。

编辑:

为了更清楚,这里是xaml中的通用代码结构

<Grid Height="Auto">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="50" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
    <StackPanel Grid.Row="0" Orientation="Horizontal" Height="Auto" Margin="0">
        <ListView />
    </StackPanel>
    <StackPanel Grid.Row="1" Orientation="Horizontal" Height="Auto" Margin="0">
        <Label />
        <Button /> 
    </StackPanel>
</Grid>

如您所见,我目前使用 2 个堆栈面板并将它们放在不同的行中。但是即使我更改为 .Listview 仍然无法按比例调整大小。

【问题讨论】:

    标签: c# wpf listview layout resize


    【解决方案1】:

    将您的 ListView 放在 Grid 中,并为列使用“*”宽度功能:

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4*" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
    
        <ListView Grid.Column="0">...</ListView>
    </Grid>
    

    此示例中的第 0 列的宽度为“4*”,第 1 列的默认宽度为“1*”。这意味着它们之间共享“五颗星”的宽度,并且第 0 列占用其中的四个。这给了你 80% 的宽度。

    【讨论】:

    • listview控件的宽高呢?我应该为这两个属性定义一个固定值,还是只说“自动”?
    • 是的,只要去掉宽度属性,让它填满列。如果您在网格中定义行并希望它垂直自动调整高度,那么对于高度也是如此。
    • 如果我用 StackPanel 包装 Listview,我还需要改变什么?似乎 StackPanel 不接受“*”。
    • StackPanel(或 ListView)不是具有“*”宽度的东西 - ColumnDefinition 是。您不应该在子元素上指定宽度。
    【解决方案2】:

    只是一个关于我发现有效的东西的仅供参考

    Here is a Value Converter that can be used with a ListView and allow star column sizing

    来自文章:

    /// <summary>
    /// Calculates the column width required to fill the view in a GridView
    /// For usage examples, see http://leghumped.com/blog/2009/03/11/wpf-gridview-column-width-calculator/
    /// </summary>
    public class WidthConverter : IValueConverter {
    /// <summary>
    /// Converts the specified value.
    /// </summary>
    /// <param name="value">The parent Listview.</param>
    /// <param name="type">The type.</param>
    /// <param name="parameter">
    /// If no parameter is given, the remaning with will be returned.
    /// If the parameter is an integer acts as MinimumWidth, the remaining with will be returned only if it's greater than the parameter
    /// If the parameter is anything else, it's taken to be a percentage. Eg: 0.3* = 30%, 0.15* = 15%
    /// </param>
    /// <param name="culture">The culture.</param>
    /// <returns>The width, as calculated by the parameter given</returns>
    public object Convert(object value, Type type, object parameter, CultureInfo culture) {
        if(value == null) return null;
        ListView listView = value as ListView;
        GridView grdView = listView.View as GridView;
        int minWidth = 0;
        bool widthIsPercentage = parameter != null && !int.TryParse(parameter.ToString(), out minWidth);
        if(widthIsPercentage) {
            string widthParam = parameter.ToString();
            double percentage = double.Parse(widthParam.Substring(0, widthParam.Length - 1));
            return listView.ActualWidth * percentage;
        } else {
            double total = 0;
            for(int i = 0; i < grdView.Columns.Count - 1; i++) {
                total += grdView.Columns[i].ActualWidth;
            }
            double remainingWidth = listView.ActualWidth - total;
            if(remainingWidth > minWidth) { // fill the remaining width in the ListView
                return remainingWidth;
            } else { // fill remaining space with MinWidth
                return minWidth;
            }
        }            
    }
    
    public object ConvertBack(object o, Type type, object parameter, CultureInfo culture) {
        throw new NotSupportedException();
    }
    }
    

    如果你不带参数调用它,它将占据ListView中剩余的宽度:

    // fills remaining width in the ListView
    <GridViewColumn Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Converter={StaticResource WidthConverter}}">
    

    如果使用整数作为参数,则该值将作为最小宽度

    // fills remaining width in the ListView, unless the remaining width is less than the parameter
    <GridViewColumn Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Converter={StaticResource WidthConverter},ConverterParameter=200}">
    

    或者,可以用星号指定一个GridView类型的宽度,会返回ListView的百分比宽度

    // calculates 30% of the ListView width
    <GridViewColumn Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListView}},Converter={StaticResource WidthConverter},ConverterParameter=0.3*}">
    

    【讨论】:

    • 对我来说,这是在列被指定宽度之前调用的。因此grdView.Columns[i].ActualWidth 始终为零。
    • 这是一个不完整的例子。如何在xaml中声明WidthConverter?
    【解决方案3】:

    这是我用来按比例调整 WPF 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);
                }
    
                //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);
        }
    

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 2019-05-23
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 2011-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多