How apply MinWidth for ListView columns in WPF in control template?

心已入冬 提交于 2020-01-23 01:16:12

问题


Following the answer to a similar question here, I was able to set the MinWidth on the XAML page.

What I would like to do is accomplish this in the control template for all GridViewColumn's in all ListView's.

Is this possible?

Update:

I tried a simple bit of sample code below, but it does not work:

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <Style TargetType="{x:Type GridViewColumnHeader}" >
            <Setter Property="MinWidth" Value="200" />
        </Style>
    </Window.Resources>

    <Grid Width="500">
        <Border BorderBrush="Black" BorderThickness="2" Margin="20">
            <ListView SelectionMode="Single">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Header 1" Width="Auto">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="Hello There"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Header 2" Width="Auto" />
                    </GridView>
                </ListView.View>
            </ListView>
        </Border>
    </Grid>
</Window>

回答1:


If you use a GridViewColumnHeader you can handle size changes:

  <GridView>
     <GridViewColumn>
        <GridViewColumnHeader Content="HeaderContent" SizeChanged="HandleColumnHeaderSizeChanged"/> 
   ...

in Code:

    private void HandleColumnHeaderSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
    {
        if (sizeChangedEventArgs.NewSize.Width <= 60) {
            sizeChangedEventArgs.Handled = true;
            ((GridViewColumnHeader) sender).Column.Width = 60;
        }
    }



回答2:


 <ListView>
        <ListView.View>
            <GridView>
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock MinWidth="100"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                 ...more columns...
            </GridView>
        </ListView.View>
    </ListView>



回答3:


<Window.Resources>
    <Style TargetType="{x:Type GridViewColumnHeader}" >
        <Setter Property="MinWidth" Value="400" />
    </Style>
</Window.Resources>



回答4:


I stumbled into this one also. To solved it I had to do two things :

  1. Modify the ControlTemplate of ListView's header.
  2. Handle the DragDelta event of the Thumb inside the ControlTemplate.

ListView's header is GridViewColumnHeader. Shown below is a simplified version of GridViewColumnHeader's ControlTemplate. As we can see, it uses a Thumb in a Canvas to create the drag/resize effect.

PS: To obtain the complete GridViewColumnHeader ControlTemplate please refer to How to grab WPF 4.0 control default templates?

<ControlTemplate TargetType="GridViewColumnHeader">
<Grid SnapsToDevicePixels="True">
    <Border BorderThickness="0,1,0,1" Name="HeaderBorder" ...>
    <!-- omitted -->
    </Border>
    <Border BorderThickness="1,0,1,1" Name="HeaderHoverBorder" Margin="1,1,0,0" />
    <Border BorderThickness="1,1,1,0" Name="HeaderPressBorder" Margin="1,0,0,1" />
    <Canvas>
        <Thumb Name="PART_HeaderGripper">
        <!-- omitted -->
        </Thumb>
    </Canvas>
</Grid>
<ControlTemplate.Triggers>
<!-- omitted -->
</ControlTemplate.Triggers>

So In order to limit the size of GridViewColumnHeader, we need to hook Thumb's drag events(DragStarted, DragDelta, DragCompleted...etc).

Turned out all we need is the DragDelta event as long we can know the MinSize within the DragDeltaEventHandler.

Shown below is modified XAML with comment.

<Grid Width="500">
    <Border BorderBrush="Black" BorderThickness="2" Margin="20">
        <ListView SelectionMode="Single">
            <ListView.View>
                <GridView>                        
                    <GridViewColumn Header="Header 1" Width="Auto">
                        <!-- Apply a style targeting GridViewColumnHeader with MinWidth = 80 and a ControlTemplate -->
                        <GridViewColumn.HeaderContainerStyle>
                            <Style TargetType="{x:Type GridViewColumnHeader}">
                                <Setter Property="MinWidth" Value="80" />
                                <Setter Property="Control.Template" Value="{DynamicResource myGridViewColumnHeaderControlTemplate}" />
                            </Style>
                        </GridViewColumn.HeaderContainerStyle>**
                    </GridViewColumn>
                    <GridViewColumn Header="Header 2" Width="Auto" />
                </GridView>
            </ListView.View>
        </ListView>
    </Border>
</Grid>

In the myGridViewColumnHeaderControlTemplate add some XAML to:

  1. Bind GridViewColumnHeader's MinWidth to Canvas's MinWidth.
  2. Hook up Thumb's DragDelta event.
<ControlTemplate x:Key="TemplateGridViewColumnHeader" TargetType="GridViewColumnHeader">
    <!-- omitted -->
    <Canvas MinWidth="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MinWidth, Mode=OneTime}">
        <Thumb x:Name="PART_HeaderGripper" DragDelta="myGridViewColumnHeader_DragDelta">

Finally the myGridViewColumnHeader_DragDelta function:

    private void myGridViewColumnHeader_DragDelta(object sender, DragDeltaEventArgs e)
    {
        DependencyObject parent = sender as DependencyObject;

        try
        {
            do
            {
                parent = VisualTreeHelper.GetParent(parent as DependencyObject);
            } while (parent.GetType() != typeof(Canvas));

            Canvas canvas = parent as Canvas;
            if (canvas.ActualWidth + e.HorizontalChange < canvas.MinWidth)
            {
                e.Handled = true;
            }
        }
        catch
        {
        }
    }

This is the only way i find working. Do hope there is a simpler way.




回答5:


I wanted to apply a minwidth to all columns, so I wrote this:

  public static class GridViewConstraints
  {
    public static readonly DependencyProperty MinColumnWidthProperty =
        DependencyProperty.RegisterAttached("MinColumnWidth", typeof(double), typeof(GridViewConstraints), new PropertyMetadata(75d, (s,e) =>
        {
            if(s is ListView listView)
            {
                listView.Loaded += (lvs, lve) =>
                {
                    if(listView.View is GridView view)
                    {
                        foreach (var column in view.Columns)
                        {
                            SetMinWidth(listView, column);

                            ((System.ComponentModel.INotifyPropertyChanged)column).PropertyChanged += (cs, ce) =>
                            {
                                if (ce.PropertyName == nameof(GridViewColumn.ActualWidth))
                                    SetMinWidth(listView, column);
                            };
                        }
                    }
                };
            }
        }));

    private static void SetMinWidth(ListView listView, GridViewColumn column)
    {
        double minWidth = (double)listView.GetValue(MinColumnWidthProperty);

        if (column.Width < minWidth)
            column.Width = minWidth;
    }

    public static double GetMinColumnWidth(DependencyObject obj) => (double)obj.GetValue(MinColumnWidthProperty);

    public static void SetMinColumnWidth(DependencyObject obj, double value) => obj.SetValue(MinColumnWidthProperty, value);
}

Just drop it on your listview:

<ListView b:GridViewConstraints.MinColumnWidth="255" />


来源:https://stackoverflow.com/questions/10097574/how-apply-minwidth-for-listview-columns-in-wpf-in-control-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!