كيفية autosize و محاذاة بيانات GridViewColumn إلى اليمين في WPF؟




xaml listview (6)

كيف يمكنني:

  • محاذاة اليمين للنص في عمود المعرف
  • جعل كل من أعمدة الحجم التلقائي وفقا لطول النص للخلية بأطول بيانات مرئية؟

هنا هو الرمز:

<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}" Width="40"/>
            <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="100" />
            <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}"/>
        </GridView>
    </ListView.View>
</ListView>

إجابة جزئية:

بفضل Kjetil ، يعمل GridViewColumn.CellTemplate بشكل جيد ويعمل العرض التلقائي بالطبع ، ولكن عند تحديث "مجموعة" ObservativeCollection مع بيانات عرض أطول من العمود ، لا يتم تحديث أحجام الأعمدة بأنفسهم بحيث لا يعدو سوى حل العرض الأولي للبيانات:

<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="ID" Width="Auto">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Id}" TextAlignment="Right" Width="40"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="Auto" />
            <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="Auto"/>
        </GridView>
    </ListView.View>
</ListView>

أعجبني حل user1333423 إلا أنه دائمًا ما يعيد ضبط كل عمود ؛ كنت بحاجة إلى السماح بعرض بعض الأعمدة. لذلك في أعمدة هذا الإصدار ، سيكون العرض الذي تم ضبطه على "تلقائي" بحجم تلقائي ولن يتم ضبط الحجم المحدد على مبلغ ثابت تلقائيًا.

public class AutoSizedGridView : GridView
{
    HashSet<int> _autoWidthColumns;

    protected override void PrepareItem(ListViewItem item)
    {
        if (_autoWidthColumns == null)
        {
            _autoWidthColumns = new HashSet<int>();

            foreach (var column in Columns)
            {
                if(double.IsNaN(column.Width))
                    _autoWidthColumns.Add(column.GetHashCode());
            }                
        }

        foreach (GridViewColumn column in Columns)
        {
            if (_autoWidthColumns.Contains(column.GetHashCode()))
            {
                if (double.IsNaN(column.Width))
                    column.Width = column.ActualWidth;

                column.Width = double.NaN;                    
            }          
        }

        base.PrepareItem(item);
    }        
}

أعلم أن هذا متأخر جدًا ولكن هنا هو النهج الذي اتبعته:

<GridViewColumn x:Name="GridHeaderLocalSize"  Width="100">      
<GridViewColumn.Header>
    <GridViewColumnHeader HorizontalContentAlignment="Right">
        <Grid Width="Auto" HorizontalAlignment="Right">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0" Text="Local size" TextAlignment="Right" Padding="0,0,5,0"/>
        </Grid>
    </GridViewColumnHeader>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
    <DataTemplate>
        <TextBlock Width="{Binding ElementName=GridHeaderLocalSize, Path=Width, FallbackValue=100}"  HorizontalAlignment="Right" TextAlignment="Right" Padding="0,0,5,0" Text="Text" >
        </TextBlock>
    </DataTemplate>
</GridViewColumn.CellTemplate>

تكمن الفكرة الرئيسية في ربط عرض عنصر cellTemplete إلى عرض ViewGridColumn. Width = 100 هو العرض الافتراضي المستخدم حتى يتم تغيير حجمه لأول مرة. لا يوجد أي كود خلف. كل شيء في xaml.


إذا تم أيضًا تغيير حجم القائمة ، فيمكنك استخدام نمط السلوك لإعادة ضبط الأعمدة لتلائم عرض ListView الكامل. تقريبًا تمامًا مثل استخدام تعريفات grid.column

<ListView HorizontalAlignment="Stretch"
          Behaviours:GridViewColumnResize.Enabled="True">
        <ListViewItem></ListViewItem>
        <ListView.View>
            <GridView>
                <GridViewColumn  Header="Column *"
                                   Behaviours:GridViewColumnResize.Width="*" >
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox HorizontalAlignment="Stretch" Text="Example1" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>

انظر الرابط التالي لبعض الأمثلة http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto بالشفرة المصدر http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto


لجعل كل أعمدة autosize يمكنك تعيين Width = "تلقائي" على GridViewColumn.

لمحاذاة اليمين للنص في عمود المعرف يمكنك إنشاء قالب خلية باستخدام TextBlock وتعيين TextAlignment. ثم قم بتعيين ListViewItem.HorizontalContentAlignment (باستخدام نمط مع أداة تعيين على ListViewItem) لجعل قالب الخلية تعبئة GridViewCell بأكمله.

ربما يكون هناك حل أبسط ، لكن هذا يجب أن يعمل.

ملاحظة: يتطلب الحل HorizontalContentAlignment = Stretch في Window.Resources و TextAlignment = Right في CellTemplate.

<Window x:Class="WpfApplication6.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
    <Style TargetType="ListViewItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    </Style>
</Window.Resources>
<Grid>
    <ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="ID" Width="40">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Id}" TextAlignment="Right" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="Auto" />
                <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="Auto"/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>
</Window>

لقد قمت بإنشاء وظيفة لتحديث عناوين أعمدة GridView لقائمة واستدعائها كلما تم تغيير حجم النافذة أو تقوم listview بتحديثها.

public void correctColumnWidths()
{
    double remainingSpace = myList.ActualWidth;

    if (remainingSpace > 0)
    {
         for (int i = 0; i < (myList.View as GridView).Columns.Count; i++)
              if (i != 2)
                   remainingSpace -= (myList.View as GridView).Columns[i].ActualWidth;

          //Leave 15 px free for scrollbar
          remainingSpace -= 15;

          (myList.View as GridView).Columns[2].Width = remainingSpace;
    }
}

منذ أن كان لدي ItemContainerStyle كان علي وضع HorizontalContentAlignment في ItemContainerStyle

    <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=FieldDef.DispDetail, Mode=OneWay}" Value="False">
                         <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>
                <Setter Property="HorizontalContentAlignment" Value="Stretch" /> 
    ....