Как пропорционально изменить размер WPF Listview? - PullRequest
2 голосов
/ 14 июня 2011

У меня небольшая проблема с изменением размера элемента управления Listview. Я намерен пропорционально изменить его размер в соответствии с реальным размером окна.

Для начального размера Listview это 300 X 600 (ширина X высота) в пикселях. И я также установил maxHeight на 750, но его ширина осталась прежней, то есть 300.

Кроме того, в свойствах Wondow я изменил свойство SizeToContent на WidthAndHeight , так как некоторые потоки предполагают, что таким образом вы разрешаете системе определять правильный размер элемента управления после окна был изменен

Однако, это еще не работает. Поэтому я здесь, чтобы попросить о помощи. Благодарю.

P.S. в любом случае мы можем установить процентное значение для ширины и высоты в WPF? Было бы намного проще, если бы мне позволили использовать процент, например, высота = 80%.

EDIT:

Чтобы было понятнее, вот общая структура кода в 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 ]

3 голосов
/ 14 июня 2011

Поместите свой ListView в сетку и используйте функцию ширины "*" для столбца:

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

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

Столбец 0 в этом примере имеет ширину "4 *", а столбец 1 имеет ширину по умолчанию "1 *". Это означает, что между ними они имеют ширину «пять звезд», а столбец 0 занимает четыре из них. Это дает вам ширину 80%.

2 голосов
/ 11 июля 2012

Просто к вашему сведению, что я нашел, что работает

Вот конвертер значений, который можно использовать с ListView и разрешить размер столбца звезды

Из статьи:

/// <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*}">
0 голосов
/ 12 сентября 2016

Это то, что я использую для пропорционального изменения размера столбцов 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);
    }
...