如何使用文本换行获取填充视图框的文本块

5

XAML是一个页面,其中包含一个Viewbox内的项目列表。目标是在部门名称下面放置一段注释。我将我的itemscontrol的背景设置为红色,以便更容易地看到它如何填充页面。

<Grid >
    <Viewbox x:Name="slideViewBox">
        <ItemsControl x:Name="itemsControl" Background="Red" ItemsSource="{Binding JournalEntries}" Grid.IsSharedSizeScope="True">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid x:Name="ParentGrid">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <TextBlock Grid.Row="0" HorizontalAlignment="Left" Foreground="White" Text="{Binding Department}" FontSize="32"/>
                        <TextBlock x:Name="detailsTextBlock" Grid.Row="1" Foreground="White" Text="{Binding DetailedExplaination}" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="20" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Viewbox>
</Grid>

生成的结果如下: enter image description here 我理想中希望的结果是: enter image description here 请注意,在第一张图片中,详细信息TextBlock没有换行,浪费了很多可用空间。
我在Size_Changed事件处理程序中编写了一些代码,使我更接近我的目标,但还没有完全达到。我手动调整itemscontrol的宽度以强制文本换行。我只需要让它自动完成,这样它看起来就像第二张图片,在页面加载时就能实现。
private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
{
    var child = VisualTreeHelper.GetChild(slideViewBox, 0) as ContainerVisual;
    var scale = child.Transform as ScaleTransform;

    double pageheight = e.NewSize.Height;
    double pagewidth = e.NewSize.Width;
    double textHeight;
    double textWidth;

    textHeight = itemsControl.ActualHeight * scale.ScaleY;
    textWidth = itemsControl.ActualWidth * scale.ScaleX;

    if (textWidth == pagewidth)
    {
        itemsControl.Width = itemsControl.ActualWidth * .9;
    }
    else if (textHeight == pageheight)
    {
        itemsControl.Width = itemsControl.ActualWidth * 1.1;
    }
}
2个回答

3
我将 @user3284736 的固定内部内容宽度的想法进行了拓展。
首先,在视图模型中添加一个属性“ContainerWidth”,并通过处理视图的 “SizeChanged” 事件来保持其更新:
public MyUserControl()
{
    SizeChanged += OnSizeChanged;
}

void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
    ViewModel.ContainerWidth= e.NewSize.Width;
}

现在将项目模板的容器(例如示例中的“ParentGrid”)的宽度绑定到整体容器大小:
<Grid x:Name="ParentGrid" 
      Width="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ContainerWidth}">

设置固定大小会强制文本在ViewBox应用其缩放之前换行。

Viewbox

编辑 这是我用来测试的XAML:

<Grid x:Name="LayoutRoot" Background="Red">
    <Viewbox Stretch="Fill" StretchDirection="Both">
        <ItemsControl x:Name="itemsControl" ItemsSource="{Binding JournalEntries}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid x:Name="ParentGrid" 
                          Width="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ContainerWidth}">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <TextBlock Grid.Row="0" HorizontalAlignment="Left" Foreground="White" Text="{Binding Department}" 
                                   FontSize="32"/>
                        <TextBlock x:Name="detailsTextBlock" Grid.Row="1" Foreground="White" Text="{Binding DetailedExplanation}" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="20" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Viewbox>
</Grid>

你能添加更多的代码吗?我还不清楚你在ViewModel中使用ContainerWidth属性是用来做什么的。 - Jon Dosmann
1
@JonD 我犯了一个错误 - 我在那里写成了"WindowWidth"而不是"ContainerWidth"。现在应该是正确的了。 - McGarnagle

2
以下更改在我包含的简化示例中有效(没有数据绑定,但这不应该有影响):
  1. 更新Viewbox,将其VerticalAlignment设置为Top
  2. 更新“inner”网格,将其VerticalAlignment设置为Stretch,并将其MaxWidth绑定到父级的ActualWidth(在我的示例中,是一个Window...不确定您的父控件是什么-您必须指定父级的x:Name)
这不会垂直地拉伸所有内容,但它确实使网格尊重窗口的宽度并包装文本。
有关绑定到父控件宽度的更多信息,请参见此处:https://dev59.com/DEXRa4cB1Zd3GeqPpi0Y#157780
<Window x:Class="StretchBoxWithWrapping.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" 
    x:Name="MyWindow"
    Height="350" 
    Width="525">
<Grid>
    <Viewbox x:Name="MyViewBox" VerticalAlignment="Top">
        <Grid x:Name="MyParentGrid" Background="Red" VerticalAlignment="Stretch"
              MaxWidth="{Binding ElementName=MyWindow,Path=ActualWidth}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" HorizontalAlignment="Left" Foreground="White" Text="Department A" FontSize="32"/>
            <TextBlock x:Name="detailsTextBlock" Grid.Row="1" Foreground="White" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="20"
                       Text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. " />
        </Grid>
    </Viewbox>
</Grid>


我试了一下你的代码,似乎和我的做的一样,唯一的区别是它在页面顶部而不是中间。文本没有换行。 - Jon Dosmann
@JonD 我认为这是正确的想法。如果你可以将项模板(“ParentGrid”)的宽度限制为窗口大小,那么这就是你所需要的。 - McGarnagle
这不会导致文本换行。如果我将网格的宽度设置为小于视图框内部伸展到的宽度,则文本在较窄的网格内换行会导致高度增加,然后整个内容通过ViewBox放大以更好地适应页面。 - Jon Dosmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接