DataGrid 内的 TextWrapping

发布于 2024-12-26 11:16:41 字数 2397 浏览 0 评论 0原文

目标

我有一个 WPF 应用程序,其中包含 DataGrid 内的文本。 我希望文本包裹在每个单元格内。 我还想为每列设置一个 MinWidth,如果必须的话,ScrollViewer 应该创建水平滚动条。 我从不希望任何单元格或 DataGrid 本身出现水平滚动条。 如果用户调整窗口大小,行应该增大或缩小以适应文本换行,但不应该允许行变得太细而不再可读。

问题

现在,文本没有换行,因为它位于滚动查看器中。 我知道可以更改此示例以使文本换行的不同方法,但我无法让它完全按照我想要的方式运行,如上所述。

简化的XAML

<Window x:Class="SampleApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SampleApp"
    Title="App" Height="350" Width="525">

    <Window.Resources>
        <Style x:Key="WrappingTextBlock" TargetType="TextBlock">
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
        <Style x:Key="WrappingTextBox" TargetType="TextBox">
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
    </Window.Resources>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Stuff ... />

        <MoreStuff ... />

        <Border Grid.Row="1" Grid.Column="1">
            <ScrollViewer>
                <StackPanel>    
                    <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding AwesomeObject, Mode=TwoWay}" Margin="5" AutoGenerateColumns="False">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="#" Binding="{Binding Number, Mode=TwoWay}"/>
                            <DataGridTextColumn Header="Header" Binding="{Binding Data, Mode=TwoWay}"/>
                            <DataGridTextColumn MinWidth="50" Header="Long Text" Binding="{Binding SoMuchText, Mode=TwoWay}" ElementStyle="{StaticResource WrappingTextBlock}" EditingElementStyle="{StaticResource WrappingTextBox}"/>
                        </DataGrid.Columns>
                    </DataGrid>
                </StackPanel>
            </ScrollViewer>
        </Border>
    </Grid>
</Window>

Goal

I have a WPF application that contain text inside a DataGrid.
I want the text to wrap inside each cell.
I also want to set a MinWidth for each column and if it has to, the ScrollViewer should create the horizonatl scroll bar.
I never want a horizontal scroll bar to appear for the any of the cells or the DataGrid itself.
If the user resizes the window, the rows should grow or shrink to accommodate the text wrapping, but it shouldn't allow the coulmns get so thin that they are no longer readable.

Problem

Right now, the text doesn't wrap because it is in a scrollviewer.
I know of different ways that I can change this sample to get the text to wrap, but I can't get it to act exactly how I want it, as mentioned above.

Simplified xaml

<Window x:Class="SampleApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SampleApp"
    Title="App" Height="350" Width="525">

    <Window.Resources>
        <Style x:Key="WrappingTextBlock" TargetType="TextBlock">
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
        <Style x:Key="WrappingTextBox" TargetType="TextBox">
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
    </Window.Resources>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Stuff ... />

        <MoreStuff ... />

        <Border Grid.Row="1" Grid.Column="1">
            <ScrollViewer>
                <StackPanel>    
                    <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding AwesomeObject, Mode=TwoWay}" Margin="5" AutoGenerateColumns="False">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="#" Binding="{Binding Number, Mode=TwoWay}"/>
                            <DataGridTextColumn Header="Header" Binding="{Binding Data, Mode=TwoWay}"/>
                            <DataGridTextColumn MinWidth="50" Header="Long Text" Binding="{Binding SoMuchText, Mode=TwoWay}" ElementStyle="{StaticResource WrappingTextBlock}" EditingElementStyle="{StaticResource WrappingTextBox}"/>
                        </DataGrid.Columns>
                    </DataGrid>
                </StackPanel>
            </ScrollViewer>
        </Border>
    </Grid>
</Window>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

攒眉千度 2025-01-02 11:16:41

尝试将列的宽度设置为“*”,

 <Border Grid.Row="1" Grid.Column="1">
     <ScrollViewer>
         <StackPanel>
             <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding AwesomeObject, Mode=TwoWay}" Margin="5" AutoGenerateColumns="False">
                 <DataGrid.Columns>
                     <DataGridTextColumn Width="10*" Header="#" Binding="{Binding Number, Mode=TwoWay}"/>
                     <DataGridTextColumn Width="10*" Header="Header" Binding="{Binding Data, Mode=TwoWay}"/>
                     <DataGridTextColumn Width="50*" Header="Long Text" Binding="{Binding SoMuchText, Mode=TwoWay}" ElementStyle="{StaticResource WrappingTextBlock}" EditingElementStyle="{StaticResource WrappingTextBox}"/>
                 </DataGrid.Columns>
             </DataGrid>
         </StackPanel>
     </ScrollViewer>
 </Border>

这意味着第 1 列的最小长度为 10,并且不断增长
这意味着第 2 列的长度至少为 10,并且不断增长
这意味着第 3 列的长度至少为 50,并且不断增长。

您可以使用百分比 (.Number*) 或长度 (Number*) 调整 * 大小

Try setting the Width of the Columns to "*"

 <Border Grid.Row="1" Grid.Column="1">
     <ScrollViewer>
         <StackPanel>
             <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding AwesomeObject, Mode=TwoWay}" Margin="5" AutoGenerateColumns="False">
                 <DataGrid.Columns>
                     <DataGridTextColumn Width="10*" Header="#" Binding="{Binding Number, Mode=TwoWay}"/>
                     <DataGridTextColumn Width="10*" Header="Header" Binding="{Binding Data, Mode=TwoWay}"/>
                     <DataGridTextColumn Width="50*" Header="Long Text" Binding="{Binding SoMuchText, Mode=TwoWay}" ElementStyle="{StaticResource WrappingTextBlock}" EditingElementStyle="{StaticResource WrappingTextBox}"/>
                 </DataGrid.Columns>
             </DataGrid>
         </StackPanel>
     </ScrollViewer>
 </Border>

This means that Column 1 will be minimum 10 length and growing
This means that Column 2 will be minimum 10 length and growing
This means that Column 3 will be minimum 50 length and growing

You can play with the * resizing using percentages (.Number*) or lengths (Number*)

咽泪装欢 2025-01-02 11:16:41

您不需要将dataGrid放入scrollViewer中...您应该设置DataGrid的MAXWidth/Maxheighjt,以便scrollViewr(已经存在于dataGrid中)将会出现......另外,如果您想要换行单元格文本

                <WPFToolkit:DataGrid Name="programListDataGrid"
                                     AutoGenerateColumns="False"
                                     CanUserAddRows="False"
                                     CanUserDeleteRows="False"
                                     CanUserReorderColumns="False"
                                     IsReadOnly="True"
                                     ItemsSource="{Binding Path=MyList}"
                                     RowStyle="{StaticResource ResourceKey=dataGridRowStyle}"
                                     SelectedItem="{Binding Path=MyItem,
                                                            Mode=TwoWay}"
                                     SelectionMode="Single">
                    <WPFToolkit:DataGrid.Columns>
                        <WPFToolkit:DataGridTextColumn MinWidth="100"
                                                       MaxWidth="250"
                                                       Binding="{Binding Path=ItemName}"
                                                       Header="Item Name" />

                        <WPFToolkit:DataGridTemplateColumn                                                                Width="*"
                                                           MinWidth="200"
                                                           Header="ItemData1">
                            <WPFToolkit:DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding ApplicationPath}"
                                               TextWrapping="Wrap"
                                               ToolTip="{Binding ItemData1}" />
                                </DataTemplate>
                            </WPFToolkit:DataGridTemplateColumn.CellTemplate>
                        </WPFToolkit:DataGridTemplateColumn>
                        <WPFToolkit:DataGridTemplateColumn                                                                Width="*"
                                                           MinWidth="200"
                                                           Header="ItemData2">
                            <WPFToolkit:DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding StandardCLP}"
                                               TextWrapping="Wrap"
                                               ToolTip="{Binding ItemData2}" />
                                </DataTemplate>
                            </WPFToolkit:DataGridTemplateColumn.CellTemplate>
                        </WPFToolkit:DataGridTemplateColumn>
                    </WPFToolkit:DataGrid.Columns>
                </WPFToolkit:DataGrid>

TextBlock 将在空间被消耗后换行...我还没有尝试使用 ElementStyle 但也应该使用它..所有宽度和高度仅供演示应该使用你的 onw 值作为 必需的... :)

You Dont need to put the dataGrid in a scrollViewer... you should set the MAXWidth/Maxheighjt of the DataGrid so that scrollViewr(already present in dataGrid) will appear...... Also if the you wnat to Wrap the Cell text

                <WPFToolkit:DataGrid Name="programListDataGrid"
                                     AutoGenerateColumns="False"
                                     CanUserAddRows="False"
                                     CanUserDeleteRows="False"
                                     CanUserReorderColumns="False"
                                     IsReadOnly="True"
                                     ItemsSource="{Binding Path=MyList}"
                                     RowStyle="{StaticResource ResourceKey=dataGridRowStyle}"
                                     SelectedItem="{Binding Path=MyItem,
                                                            Mode=TwoWay}"
                                     SelectionMode="Single">
                    <WPFToolkit:DataGrid.Columns>
                        <WPFToolkit:DataGridTextColumn MinWidth="100"
                                                       MaxWidth="250"
                                                       Binding="{Binding Path=ItemName}"
                                                       Header="Item Name" />

                        <WPFToolkit:DataGridTemplateColumn                                                                Width="*"
                                                           MinWidth="200"
                                                           Header="ItemData1">
                            <WPFToolkit:DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding ApplicationPath}"
                                               TextWrapping="Wrap"
                                               ToolTip="{Binding ItemData1}" />
                                </DataTemplate>
                            </WPFToolkit:DataGridTemplateColumn.CellTemplate>
                        </WPFToolkit:DataGridTemplateColumn>
                        <WPFToolkit:DataGridTemplateColumn                                                                Width="*"
                                                           MinWidth="200"
                                                           Header="ItemData2">
                            <WPFToolkit:DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding StandardCLP}"
                                               TextWrapping="Wrap"
                                               ToolTip="{Binding ItemData2}" />
                                </DataTemplate>
                            </WPFToolkit:DataGridTemplateColumn.CellTemplate>
                        </WPFToolkit:DataGridTemplateColumn>
                    </WPFToolkit:DataGrid.Columns>
                </WPFToolkit:DataGrid>

The TextBlock will wrap after the space is consumed... I have not tried this with ElementStyle but should work with that too.. All the width and height just for demo you should use your onw values as required... :)

梦罢 2025-01-02 11:16:41

我的解决方案解决了当人们希望 Header 文本换行时的情况 - 也可以控制列的宽度。我使用内置的 DataGridTextColumn,但为其提供自定义的 HeaderTemplate,我可以在其中控制文本的换行:

<DataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Axle Group No."/> <!-- this stays with defaults -->
        <DataGridTextColumn Header="Axle Group Load Measured :(a)" MaxWidth="100"  ><!-- NOTE: MaxWidth and template below -->
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" TextWrapping="Wrap" />
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
        </DataGrid.Columns>
</DataGrid>

如果您也希望为数据单元格自定义文本换行,则最好使用完全可自定义的列类型DataGridTemplateColumn。该类型允许您以类似于以下的方式指定 HeaderTemplateCellTemplate

<DataGrid>
   <DataGrid.Columns>
      <DataGridTemplateColumn>
         <DataGridTemplateColumn.HeaderTemplate>
            <DataTemplate>
               <TextBlock Text="{Binding}" TextWrapping="Wrap" />
            </DataTemplate>
         </DataGridTemplateColumn.HeaderTemplate>
         <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
               <TextBlock Text="{Binding}" TextWrapping="Wrap" />
            </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
   </DataGrid.Columns>
</DataGrid>

My solution tackles the scenario for when one wishes to have the Header text wrap - with control for how wide the column should be too. I use the inbuilt DataGridTextColumn, but provide it a custom HeaderTemplate in which I control the wrapping of the text:

<DataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Axle Group No."/> <!-- this stays with defaults -->
        <DataGridTextColumn Header="Axle Group Load Measured :(a)" MaxWidth="100"  ><!-- NOTE: MaxWidth and template below -->
            <DataGridTextColumn.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" TextWrapping="Wrap" />
                </DataTemplate>
            </DataGridTextColumn.HeaderTemplate>
        </DataGridTextColumn>
        </DataGrid.Columns>
</DataGrid>

If you wish to customizing text wrapping for the data cells too, then it's better you use the fully customizable column type DataGridTemplateColumn. That type allows you to specify either the HeaderTemplate or the CellTemplate in a manner similar to this:

<DataGrid>
   <DataGrid.Columns>
      <DataGridTemplateColumn>
         <DataGridTemplateColumn.HeaderTemplate>
            <DataTemplate>
               <TextBlock Text="{Binding}" TextWrapping="Wrap" />
            </DataTemplate>
         </DataGridTemplateColumn.HeaderTemplate>
         <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
               <TextBlock Text="{Binding}" TextWrapping="Wrap" />
            </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
   </DataGrid.Columns>
</DataGrid>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文