如何按比例调整WPF Listview的大小?

时间:2011-06-14 04:03:54

标签: c# wpf listview layout resize

调整Listview控件的大小有点问题。我打算根据窗口的实际大小按比例调整大小。

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

另外,在Wondow的属性中,我已将 SizeToContent 属性更改为 WidthAndHeight ,因为有些线程建议您通过这样做让系统决定控件的正确大小窗口大小调整后。

然而,它尚未奏效。所以我来这里寻求帮助。谢谢。

P.S。无论如何我们可以在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仍然无法按比例调整大小。

3 个答案:

答案 0 :(得分:3)

将ListView放在网格中,并使用列的“*”宽度功能:

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

    <ListView Grid.Column="0">...</ListView>
</Grid>

此示例中的第0列的宽度为“4 *”,第1列的默认宽度为“1 *”。这意味着它们之间的宽度为“五颗星”,第0列则为四颗。这样可以获得80%的宽度。

答案 1 :(得分:2)

我发现有效的东西只是一个FYI

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*}">

答案 2 :(得分:0)

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