Низкая производительность при динамическом изменении размера текстового блока WPF - PullRequest
1 голос
/ 10 июля 2009

В настоящее время я разрабатываю макет приложения WPF и, похоже, он немного загвоздка в макете одного из моих элементов управления. Этот элемент управления динамически изменяет размер, поэтому он должен соответствовать размеру области просмотра, частью которой он является. Проблема, с которой я сталкиваюсь, является очень визуальной проблемой, поэтому я приложу все усилия, чтобы описать ее. Вот как это выглядит на данный момент:

альтернативный текст http://gallery.me.com/theplatz/100006/Capture/web.png?ver=12472534170001

Область под каждым из заголовков «Col N Row X» представляет собой текстовый блок, в который будет помещен текст различной длины. Чтобы сделать TextBlock действительно переносимым, я нашел здесь решение для stackoverflow, в котором говорится, что необходимо привязать ширину текстового блока к ширине столбца. Вот фрагмент определения Grid вместе с определением для первого столбца:

<!-- 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}"

на каждом из текстовых блоков. Проблема также становится заметно хуже, чем больше этих элементов управления на экране одновременно. Но без этой строки текст внутри каждого из текстовых блоков будет продолжать расти вправо, чем больше текста будет добавлено, а не будет перенесено в столбец.

Есть ли лучший способ выполнить то, что я пытаюсь сделать? Используя HTML / CSS, это было бы довольно просто сделать. Я часами гуглял и просматривал stackoverflow, чтобы найти ответ на этот вопрос.

Я пришел из глубокого фона HTML / CSS, поэтому, если это не то, что WPF должен быть хорош, пожалуйста, дайте мне знать.

Ответы [ 3 ]

1 голос
/ 10 марта 2010

Я не хочу отвечать на свой вопрос, но, похоже, я понял, что делал неправильно. Так как прошло так много времени с тех пор, как был задан первоначальный вопрос, я не могу вспомнить каждый шаг, который я пытался сделать, но это то, что я знаю. Стиль каждого текстового блока был задан следующим образом:

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

В то время я предполагаю, что это не дало желаемых результатов, и поэтому мне пришлось привязать ширину текстового блока к ширине столбца. Проигрывая сегодня, я изменил стиль на следующий (обратите внимание на горизонтальное выравнивание), удалил привязки и обнаружил, что моя проблема была решена:

<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>
0 голосов
/ 23 сентября 2009

Надеюсь, я не неправильно истолковал ваш вопрос, но не вижу необходимости в привязке 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».

0 голосов
/ 13 июля 2009

Я извиняюсь, если вы попробовали это, но разве установка TextBlock.TextWrapping на "Wrap" не достигла вашей цели?

Полагаю, это избавит вас от необходимости делать вещи, привязанные к ширине, так как Grid позаботится об изменении размера. (Это, вероятно, то, что происходит сейчас: Сетка раскладывает элементы управления по мере того, как она сжимается, а привязка к ширине слегка меняет размер, вызывая танец.)

[Update]

Я пытался продублировать поведение, которое вы видите, но у меня оно работает нормально. Я сделал простой стиль для TextBlocks примерно так:

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

А у меня не было других ваших динамических ресурсов (DetailHeadingBorder, DetailHeadingText, or ColumnBorderBrush), поэтому все было черно-белым (хорошо).

Может быть, у вас просто очень старая видеокарта, и она выполняет рендеринг программно? Или это связано с вашим styles.

...