开发者

How to resize WPF Listview proportionally?

I have a little bit problem with resizing Listview control. I intend to make it resize proportionally, according to the actual size of the window.

For initial size of Listview, it's 300 X 600 (width X height) in pixels. And I also set its maxHeight to 750, but its width stays the same, i.e. 300.

Also, in Wondow's properties, I have changed SizeToContent property to WidthAndHeight, as some of the threads suggest by doing so you let system decide the proper size of the control after window's been resized.

However, it's not yet working. So I am here to ask for help. Thanks.

P.S. is there anyway we can set percentage value for width and height in WPF? That'开发者_StackOverflow中文版d be a lot easier if I am allowed to use percentage, like height = 80%.

EDIT:

To make it clearer, here is the general code structure in 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>

As you can see, I am currently using 2 stack panels and put them in separate rows. But Listview still can't resize proportionally even if I change to .


Place your ListView inside a Grid, and use the "*" width feature for the column:

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

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

Column 0 in this example has a width of "4*" and column 1 has the default width of "1*". That means that between them they share a width of "five stars" and column 0 takes four of them. That gives you an 80% width.


Just an FYI on something that I found that works

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

From the article:

/// <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();
}
}

If you call it with no parameters, it’ll take up the remaining width in the ListView:

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

If you use an integer as a parameter, the value will act as the minimum width

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

Or, you can specify a GridView type width with an asterisk, and the percentage width of the ListView will be returned

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


This is what I am using to proportionally resize the columns of a WPF ListView such that a horizontal scrollbar will not be displayed after resizing. This handles any number of columns, and the presence of a vertical scrollbar. No converter is used, only an event handler for size changed. So far, this is working well. The only drawback is the horizontal scrollbar will sometimes flash while the user is resizing the window.

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);
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜