Отображение даты и времени в текстовом блоке с пунктирной линией текста - PullRequest
0 голосов
/ 07 октября 2019

Я пытаюсь отобразить DateTime в формате 2019-10-07 17:00 в TextBlock. Текст должен быть подчеркнут и пунктир. Для этого я использую следующий xaml

<TextBlock Text="2019-10-07 17:00">
    <TextBlock.TextDecorations>
        <TextDecoration Location="Underline">
            <TextDecoration.Pen>
                <Pen Brush="Black">
                    <Pen.DashStyle>
                        <DashStyle Dashes="5"/>
                    </Pen.DashStyle>
                </Pen>
            </TextDecoration.Pen>
        </TextDecoration>
    </TextBlock.TextDecorations>
</TextBlock>

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

enter image description here

Если я поменяю знак минус-знак на неразрывный-hyphen ", который выглядит очень похоже (- vs -), рендеринг работает, как и ожидалось.

<TextBlock Text="2019‐10‐07 17:00" ...>

enter image description here

Эта ошибка рендеринга пунктирной подчеркиванияпроисходит каждый раз, когда я добавляю к тексту знак минус-дефиса, но не с любым другим символом, который я смог найти. Кто-нибудь еще заметил это и есть ли у кого-нибудь решение? Если нет, то в чем может быть причина этого странного поведения?

enter image description here

Ответы [ 3 ]

1 голос
/ 08 октября 2019

Это, вероятно, результат странного взлома кода в коде рендеринга глифов WPF. В источнике .NET вы найдете метод AdjustAdvanceForDisplayLayout () и его комментарий:

// AdvanceHeight is used to compute the bounding box. In some case, eg. the dash
// character '-', the bounding box is computed to be empty in Display
// TextFormattingMode (because the metrics are rounded to be pixel aligned) and so the
// dash is not rendered!

Установка TextOptions.TextFormattingMode="Display" в TextBlock приведет к немного другому артефакту:

enter image description here

Это говорит о том, что мы действительно нашли этот «обходной путь» (см. GlyphRun.cs line 1326 ).

Итак, вопрос в том, сможем ли мы каким-то образом получить третий вариант, без каких-либо из этих артефактов. Пока что мне это не удалось, но я попытался найти, где происходит проверка дефиса. Кажется, это происходит в нативном коде. См. TextFormatterContext.cs и LoCreateContext .

0 голосов
/ 07 октября 2019

У меня нет ответа на вопрос, почему происходит такое странное поведение. Похоже, что штрихи, созданные Pen, сопоставлены с декорированным текстом TextDecoration. Это имеет смысл, поскольку штрихи или TextDecoration в целом автоматически подстраиваются, например, к размеру шрифта. Символ минус, кажется, производит другое расстояние. Возможно, такое поведение не возникает при использовании моноширинного шрифта.

В любом случае, вы можете создать мозаичный DrawingBrush и назначить его свойству Pen.Brush для создания пунктирной линии. Вы можете поиграться с DrawingBrush.ViewPort, чтобы изменить положение или длину тире.
Viewport состоит из четырех значений и на самом деле Rect, который описывает положение тайла иРазмерность: x, y, width, height. Большие значения ширины и высоты создают более длинные штрихи.
Результатом является равномерное рисование штрихов и пробелов:

<TextBlock Text="2019-10-07 17:00">
  <TextBlock.TextDecorations>
    <TextDecoration Location="Underline">
      <TextDecoration.Pen>
        <Pen>
          <Pen.Brush>
            <DrawingBrush Viewport="0,0,10,10"
                          ViewportUnits="Absolute"
                          TileMode="Tile">
              <DrawingBrush.Drawing>
                <GeometryDrawing Brush="Black">
                  <GeometryDrawing.Geometry>
                    <GeometryGroup>
                      <RectangleGeometry Rect="0,0,5,5" />
                      <RectangleGeometry Rect="5,5,5,5" />
                    </GeometryGroup>
                  </GeometryDrawing.Geometry>
                </GeometryDrawing>
              </DrawingBrush.Drawing>
            </DrawingBrush>
          </Pen.Brush>
        </Pen>
      </TextDecoration.Pen>
    </TextDecoration>
  </TextBlock.TextDecorations>
</TextBlock>

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

0 голосов
/ 07 октября 2019

Учитывая ваш формат, размер всегда должен быть примерно одинаковым, чтобы вы могли использовать другой текстовый блок, например, так и просто перекрывать другой блок

<TextBlock Text="This is a really lon" Foreground="Transparent" IsHitTestVisible="False">
    <TextBlock.TextDecorations>
        <TextDecoration Location="Underline">
            <TextDecoration.Pen>
                <Pen Brush="Black">
                    <Pen.DashStyle>
                        <DashStyle Dashes="5"/>
                    </Pen.DashStyle>
                </Pen>
            </TextDecoration.Pen>
        </TextDecoration>
    </TextBlock.TextDecorations>
</TextBlock>
<TextBlock Text="2019-10-07 17:00" />
...