【问题标题】:How do I get a textblock with textwrapping to fill a viewbox如何获得带有文本包装的文本块来填充视图框
【发布时间】:2014-09-09 02:27:31
【问题描述】:

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>

它会产生什么: 我理想中想要的:

请注意,在第一张图片中,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;
    }
}

【问题讨论】:

    标签: c# wpf word-wrap viewbox


    【解决方案1】:

    我采纳了@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 应用缩放之前强制文本换行。

    编辑 这是我用来测试的 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 属性的目的。
    • @JonD 我的错误 - 我在那里有“WindowWidth”而不是“ContainerWidth”。现在应该是正确的。
    【解决方案2】:

    以下更改在我包含的简化示例中起作用(没有数据绑定,但这不重要):

    1. 更新 Viewbox,将其 VerticalAlignment 设置为 Top
    2. 更新“内部”网格,将其 VerticalAlignment 设置为 Stretch 并将其 MaxWidth 绑定到父级的 ActualWidth(在我的示例中,一个窗口...不确定您的父控件是什么 - 您必须指定x:父级上的名称)

    这不会垂直拉伸所有内容,但它确实使网格符合 Window 的宽度并且它确实包裹了文本。

    更多关于绑定到父控件宽度的信息 - https://stackoverflow.com/a/157780/3284736

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

    【讨论】:

    • 我试用了你的代码,它似乎和我的一样,唯一的区别是它在页面顶部而不是中间。文本没有换行。
    • @JonD 不过,我认为这是正确的想法。如果您可以将项目模板(“ParentGrid”)的宽度限制为窗口大小,那么这就是您所需要的。
    • 这不会导致文本换行。如果我采用网格并将其宽度设置为小于它在视图框内延伸的宽度,那么它将导致高度增加,因为文本包裹在较窄的网格内,然后整个东西被炸毁以更好地适应页面通过 ViewBox
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    相关资源
    最近更新 更多