วิธีปรับขนาดอัตโนมัติและจัดแนวข้อมูล GridViewColumn ใน WPF โดยอัตโนมัติ


89

ฉันสามารถ:

  • จัดข้อความให้ชิดขวาในคอลัมน์ ID
  • ทำให้แต่ละคอลัมน์มีขนาดอัตโนมัติตามความยาวข้อความของเซลล์ด้วยข้อมูลที่มองเห็นได้นานที่สุด?

นี่คือรหัส:

<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 ทำงานได้ดีและความกว้างอัตโนมัติทำงานได้แน่นอน แต่เมื่อ "Collection" ของ 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>

1
คุณเคยพบวิธีแก้ปัญหาขนาดอัตโนมัติของคุณหรือไม่? ฉันกำลังประสบกับสิ่งเดียวกัน
Oskar

2
@Oskar - การจำลองเสมือนของรายการป้องกันการแก้ปัญหาอัตโนมัติ รายการจะรู้เฉพาะรายการที่มองเห็นได้ในปัจจุบันและกำหนดขนาดตามนั้น หากมีรายการเพิ่มเติมลงไปในรายการจะไม่ทราบถึงรายการเหล่านี้และไม่สามารถบันทึกบัญชีได้ หนังสือ ProgrammingWPF - Sells-Griffith แนะนำความกว้างของคอลัมน์ด้วยตนเองหากคุณใช้การผูกข้อมูล :(
Gishu

@Gishu ขอบคุณที่เข้าท่าจริงๆ ..
Oskar

หากการใช้ MVVM และค่าการผูกมีการเปลี่ยนแปลงโปรดดูคำตอบของ @Rolf Wessels
Jake Berger

คำตอบ:


104

ในการทำให้แต่ละคอลัมน์ปรับขนาดอัตโนมัติคุณสามารถตั้งค่า Width = "Auto" บน GridViewColumn

ในการจัดแนวข้อความในคอลัมน์ ID ให้ถูกต้องคุณสามารถสร้างเทมเพลตเซลล์โดยใช้ TextBlock และตั้งค่า TextAlignment จากนั้นตั้งค่า ListViewItem.HorizontalContentAlignment (โดยใช้สไตล์กับ setter บน 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>

@Kjetil - ฉันสามารถใช้การตั้งค่านี้กับคอลัมน์เฉพาะได้หรือไม่?
Gishu

15
+1 สำหรับ: <Setter Property = "HorizontalContentAlignment" Value = "Stretch" />
Helge Klein

ยอดเยี่ยม แต่ฉันมี 15 คอลัมน์มีวิธีใดบ้างที่ฉันไม่ต้องทำซ้ำ celltemplate สำหรับพวกเขาทั้งหมด?
Nitin Chaudhari

7
นอกจากนี้ยังใช้งานไม่ได้หากคุณลืมลบ DisplayMemberBinding ออกจาก GridViewColumn เทมเพลตจะไม่มีผลใด ๆ
floele

@ โมฮาเหม็ดทำไมไม่เป็น?
It'sNotALie

37

หากความกว้างของเนื้อหาเปลี่ยนไปคุณจะต้องใช้รหัสนี้เพื่ออัปเดตแต่ละคอลัมน์:

private void ResizeGridViewColumn(GridViewColumn column)
{
    if (double.IsNaN(column.Width))
    {
        column.Width = column.ActualWidth;
    }

    column.Width = double.NaN;
}

คุณจะต้องเริ่มการทำงานทุกครั้งที่ข้อมูลสำหรับคอลัมน์นั้นอัปเดต


1
คุณจะแนบสิ่งนี้กับอะไร?
Armentage

1
เรียกใช้ด้วยตนเองบน GridViewColumn หลังจากที่คุณอัปเดตข้อมูลกริด หากคุณมี ViewModel คุณสามารถสมัครรับเหตุการณ์ PropertyChanged ได้จากนั้นเรียกใช้งาน
RandomEngy

+1 ขอบคุณสำหรับสิ่งนั้น! สิ่งนี้ช่วยฉันได้มาก! ไม่เกี่ยวข้องกับคำถามนี้ แต่อย่างไรก็ตาม: ฉันใช้ List / GridView ที่กำหนดเองซึ่งคุณสามารถเพิ่ม / ลบคอลัมน์แบบไดนามิกในรันไทม์ผ่าน GUI อย่างไรก็ตามเมื่อฉันลบและเพิ่มคอลัมน์ใหม่คอลัมน์นั้นก็ไม่ปรากฏอีกต่อไป ก่อนอื่นฉันคิดว่ามันไม่ได้เพิ่มเลย (ด้วยเหตุผลบางอย่าง) แต่จากนั้น (โดยใช้ Snoop) ฉันพบว่ามีการเพิ่มจริง แต่มี ActualWidth เป็น 0 (เป็นขนาดอัตโนมัติและเห็นได้ชัดว่ารีเซ็ตเมื่อคอลัมน์เป็น ลบออก) ตอนนี้ฉันใช้รหัสของคุณเพื่อตั้งค่าคอลัมน์ให้มีความกว้างที่ถูกต้องหลังจากที่ฉันเพิ่มเข้าไปในคอลัมน์อีกครั้ง ขอบคุณมาก!
gehho

วิธีแก้ปัญหาง่ายๆ!
Gqqnbig

+1 สมบูรณ์แบบ! หวังว่านี่คือคำตอบ ฉันเพิ่ม x: Name = "gvcMyColumnName" ลงใน XAML ซึ่งมีการกำหนดคอลัมน์เพื่อให้ฉันสามารถเข้าถึงได้ในโค้ดด้านหลัง ทำงานเหมือนแชมป์
K0D4

19

หากมุมมองรายการของคุณมีการปรับขนาดใหม่ด้วยคุณสามารถใช้รูปแบบพฤติกรรมเพื่อปรับขนาดคอลัมน์ใหม่ให้พอดีกับความกว้าง 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


อันนี้เด็ดเลย แก้ไขปัญหาและมอบฟังก์ชันn , Auto ทั้งหมดที่คุณกำลังมองหา
Designpattern

นี่คือสิ่งที่ฉันกำลังมองหา : D
Jake Berger

หมายเหตุ: ดูเหมือนจะมีข้อบกพร่อง เมื่อ ListView ถูกปรับขนาดในแนวตั้งไปยังจุดที่ทำให้แถบเลื่อนแนวตั้งปรากฏขึ้นคอลัมน์จะเพิ่มความกว้างอย่างต่อเนื่องจนกว่าแถบเลื่อนจะหายไป
Jake Berger

1
โพสต์นี้อาจให้ข้อมูลเชิงลึกเกี่ยวกับพฤติกรรมที่อธิบายไว้ในความคิดเห็นก่อนหน้าของฉัน
Jake Berger

มันเจ๋งมากฉันหมายถึงทั้งโค้ดและไซต์ :) ฉันเชื่อว่าจะมีประโยชน์เมื่อฉันมีข้อกำหนดที่เข้มงวดขึ้น
Gqqnbig

12

ฉันได้สร้างคลาสต่อไปนี้และใช้กับแอปพลิเคชันทุกที่ที่ต้องการแทนGridView:

/// <summary>
/// Represents a view mode that displays data items in columns for a System.Windows.Controls.ListView control with auto sized columns based on the column content     
/// </summary>
public class AutoSizedGridView : GridView
{        
    protected override void PrepareItem(ListViewItem item)
    {
        foreach (GridViewColumn column in Columns)
        {
            // Setting NaN for the column width automatically determines the required
            // width enough to hold the content completely.

            // If the width is NaN, first set it to ActualWidth temporarily.
            if (double.IsNaN(column.Width))
              column.Width = column.ActualWidth;

            // Finally, set the column with to NaN. This raises the property change
            // event and re computes the width.
            column.Width = double.NaN;              
        }            
        base.PrepareItem(item);
    }
}

7

เนื่องจากฉันมี 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" /> 
    ....

6

ฉันชอบโซลูชันของ 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);
    }        
}

2

ฉันรู้ว่ามันสายเกินไป แต่นี่คือแนวทางของฉัน:

<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


สิ่งนี้เป็นแรงบันดาลใจให้ฉันใช้โซลูชันนี้เพื่อเติมความกว้างของคอลัมน์หนึ่งคอลัมน์: <GridViewColumn Width = "{Binding RelativeSource = {RelativeSource AncestorType = ListView}, Path = ActualWidth}">
J. Andersen

1

ฉันมีปัญหากับคำตอบที่ยอมรับ (เพราะฉันพลาดส่วน HorizontalAlignment = Stretch และได้ปรับคำตอบเดิม)

นี่เป็นอีกหนึ่งเทคนิค ใช้ Grid กับ SharedSizeGroup

หมายเหตุ: Grid.IsSharedScope = trueบน ListView

<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">
<Grid>
    <ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}" Grid.IsSharedSizeScope="True">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="ID" Width="40">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                             <Grid>
                                  <Grid.ColumnDefinitions>
                                       <ColumnDefinition Width="Auto" SharedSizeGroup="IdColumn"/>
                                  </Grid.ColumnDefinitions>
                                  <TextBlock HorizontalAlignment="Right" Text={Binding Path=Id}"/>
                             </Grid>
                        </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>

คุณมีความกว้างGridViewColumnเป็น40และคุณตั้งค่าความกว้างนิยามคอลัมน์เป็นAuto? นั่นไม่สมเหตุสมผล
BK

1

ฉันสร้างฟังก์ชันสำหรับอัปเดตส่วนหัวคอลัมน์ GridView สำหรับรายการและเรียกใช้เมื่อใดก็ตามที่มีการปรับขนาดหน้าต่างใหม่หรือมุมมองรายการจะอัปเดตเค้าโครง

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

0

นี่คือรหัสของคุณ

<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>

ลองทำตามนี้

<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Id}" Width="Auto">
               <GridViewColumnHeader Content="ID" Width="Auto" />
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding FirstName}" Width="Auto">
              <GridViewColumnHeader Content="First Name" Width="Auto" />
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding LastName}" Width="Auto">
              <GridViewColumnHeader Content="Last Name" Width="Auto" />
            </GridViewColumn
        </GridView>
    </ListView.View>
</ListView>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.