【问题标题】:Poor Performance When Dynamically Resizing a WPF TextBlock动态调整 WPF TextBlock 的大小时性能不佳
【发布时间】:2014-08-21 17:18:54
【问题描述】:

我目前正在制定 WPF 应用程序的布局,并且似乎在我的一个控件的布局中遇到了一些障碍。此控件是动态调整大小的,因此它应该适合它所在的视口的大小。我遇到的问题是一个非常直观的问题,所以我会尽力描述它。这是它目前的样子:

alt text http://gallery.me.com/theplatz/100006/Capture/web.png?ver=12472534170001

每个“Col N Row X”标题下方的区域是一个 TextBlock,其中将放置不同长度的文本。为了使 TextBlock 真正换行,我在 stackoverflow 上找到了一个解决方案,它说将文本块的宽度绑定到列的宽度。这是 Grid 定义的 sn-p 以及第一列的定义:

<!-- Change Detail Contents Grid -->
<Grid Grid.Row="1">
    <Grid.ColumnDefinitions>
    <ColumnDefinition MinWidth="270" Width="2*" />
    <ColumnDefinition MinWidth="160" Width="*" />
    <ColumnDefinition MinWidth="160" Width="*" />
    <ColumnDefinition MinWidth="160" Width="*" />
    </Grid.ColumnDefinitions>

    <!-- 
    We bind the width of the textblock to the width of this border to make sure things resize correctly.
    It's important that the margin be set to 1 larger than the margin of the textblock or else you'll end
    up in an infinate loop 
    -->
    <Border Grid.Column="0" Margin="6" Name="FirstBorder" />
    <Border Grid.Column="0" BorderThickness="0,0,1,0" BorderBrush="{DynamicResource   ColumnBorderBrush}">
    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <StackPanel Grid.Row="0">
        <Border Style="{DynamicResource DetailHeadingBorder}">
                <TextBlock Text="Col 1 Row 1" Style="{DynamicResource DetailHeadingText}" />
            </Border>
                <TextBlock Text="{Binding IsReason, ElementName=ChangeDetailRoot}" Style="{DynamicResource DetailText}" Width="{Binding ActualWidth, ElementName=FirstBorder}" />
            </StackPanel>

    <StackPanel Grid.Row="1">
            <Border Style="{DynamicResource DetailHeadingBorder}">
            <TextBlock Text="Col 1 Row 2" Style="{DynamicResource DetailHeadingText}" />
            </Border>
        <TextBlock Text="{Binding WasReason, ElementName=ChangeDetailRoot}" Style="{DynamicResource DetailText}" Width="{Binding ActualWidth, ElementName=FirstBorder}" />
    </StackPanel>   
    </Grid>
    </Border>
</Grid>

当窗口/视口宽度增加时,一切都可以很好地调整大小。当宽度减小时问题变得明显。如果你突然从最大化到原始大小,所有的列都会“跳舞”回到它们指定的大小。我的意思是您可以看到每列的大小都缩小了,因为它按比例调整回其较小的大小。我发现这是直接由

Width="{Binding ActualWidth, ElementName=FirstBorder}"

在每个文本块上。当这些控件同时出现在屏幕上时,问题也会变得明显更糟。但是,如果没有该行,每个 TextBlock 中的文本将继续向右增长,添加的文本越多,而不是在列中向下换行。

有没有更好的方法来完成我想要完成的事情?使用 HTML/CSS,这将是一件相当简单的事情。我花了几个小时在谷歌上搜索并通过 stackoverflow 寻找这个问题的答案。

我来自 HTML/CSS 的丰富背景,所以如果这不是 WPF 应该擅长的,请告诉我。

【问题讨论】:

标签: wpf performance grid textblock


【解决方案1】:

我不想回答我自己的问题,但我似乎发现了我做错了什么。由于距离最初的问题已经很久了,我不记得我试图采取的每一步,但这是我所知道的。每个文本块的样式设置如下:

<Style x:Key="DetailText" TargetType="TextBlock">
    <Setter Property="HorizontalAlignment" Value="Center" /> 
    <Setter Property="TextWrapping" Value="Wrap" /> 
    <Setter Property="TextAlignment" Value="Center" />
    <Setter Property="Margin" Value="5,5,5,5" />
</Style>

当时,我假设没有产生预期的结果,因此我必须将文本块的宽度绑定到列的宽度。今天在玩的时候,把样式改成下面这样(注意不同的Horizo​​ntalAlignment),去掉绑定,发现我的问题已经解决了:

<Style x:Key="DetailText" TargetType="TextBlock">
    <Setter Property="HorizontalAlignment" Value="Stretch" />
    <Setter Property="TextWrapping" Value="Wrap" />
    <Setter Property="TextAlignment" Value="Center" />
    <Setter Property="Margin" Value="5,5,5,5" />
</Style>

【讨论】:

    【解决方案2】:

    如果您尝试过此操作,我深表歉意,但是将 TextBlock.TextWrapping 设置为“Wrap”是否无法实现您的目标?

    我猜这将消除您对绑定到宽度的需求,因为 Grid 将负责调整大小。 (这可能是现在正在发生的事情:网格在缩小时正在布置控件,并且与宽度的绑定正在稍微改变大小,从而导致跳舞。)

    [更新]

    我试图复制您看到的行为,但它对我来说很好。我为 TextBlocks 做了一个简单的样式,如下所示:

    <Style x:Key="DetailText" TargetType="{x:Type TextBlock}">
        <Setter Property="TextBlock.TextWrapping" Value="Wrap"/>                
    </Style>
    

    而且我没有你的任何其他动态资源 (DetailHeadingBorder, DetailHeadingText, or ColumnBorderBrush),所以一切都是黑白的(很好)。

    也许你只是有一个非常旧的显卡,它正在用软件渲染东西?或者它与您的styles 有关。

    【讨论】:

    • 我想我应该将样式与 XAML 一起包含,但我正在这样做。即使打开了,除非文本块上设置了宽度,否则文本不会换行。
    【解决方案3】:

    希望我没有误解您的问题,但我认为不需要绑定 TextBlock.Width?

    这个 xaml 似乎工作正常:

      <Grid>
         <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="270"
                              Width="2*" />
            <ColumnDefinition MinWidth="160"
                              Width="*" />
            <ColumnDefinition MinWidth="160"
                              Width="*" />
            <ColumnDefinition MinWidth="160"
                              Width="*" />
         </Grid.ColumnDefinitions>
         <!--     We bind the width of the textblock to the width of this border to make sure things resize correctly.    
               It's important that the margin be set to 1 larger than the margin of the textblock or else you'll end  
                 up in an infinate loop     -->
         <Border Grid.Column="0"
                 BorderThickness="0,0,1,0">
            <Grid>
               <Grid.RowDefinitions>
                  <RowDefinition Height="*" />
                  <RowDefinition Height="*" />
               </Grid.RowDefinitions>
               <StackPanel Grid.Row="0">
                  <Border>
                     <TextBlock Text="Col 1 Row 1" />
                  </Border>
                  <TextBlock TextWrapping="Wrap"
                             Text="gfege dfh lh dfl dhliöslghklj h lglsdg fklghglfg flg lgheh" />
               </StackPanel>
               <StackPanel Grid.Row="1">
                  <Border>
                     <TextBlock Text="Col 1 Row 2" />
                  </Border>
                  <TextBlock Text="Massor av text som blir en wrappning i slutändan hoppas jag"
                             TextWrapping="Wrap" />
               </StackPanel>
            </Grid>
         </Border>
      </Grid>
    

    我刚刚删除了宽度绑定,添加了 TextWrapping(您可能在样式中拥有),并且还删除了名为“FirstBorder”的边框。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      • 2018-03-08
      • 2012-07-29
      • 2021-04-06
      • 2012-05-11
      相关资源
      最近更新 更多