#wpf #render #textblock
#wpf #визуализация #текстовый блок
Вопрос:
Я создал пользовательский элемент управления WPF, уникальной функцией которого является отображение текста.
Я пытался использовать TextBlock
из System.Windows.Controls
пространства имен, но у меня это не работает (у меня ~ 10000 строк с разной позицией и слишком большой потерей памяти).
Итак, я попытался создать свой собственный элемент управления, унаследовав FrameworkElement, переопределяющий OnRender
метод, который теперь содержит одну строку:
drawingContext.DrawText(...);
Но…
Я получаю немного запутанный результат.
После сравнения производительности для 10000 объектов я понял, что время, необходимое для создания и добавления в Canvas, по-прежнему составляет ~ 10 секунд, а использование памяти для моего приложения увеличивается с ~ 32 МБ до ~ 60 МБ!!!
Так что никаких преимуществ вообще.
Кто-нибудь может объяснить, почему это происходит, и каков другой способ создать простой (простой = выделять меньше памяти, создавать меньше времени) визуальный с двумя функциями:
- отображение текста
- установите положение (используя толщину или
TranslateTransform
)
Спасибо.
Комментарии:
1. Не могли бы вы опубликовать код того, что вы именно делаете? Также не совсем понятно, почему
TextBlock
это вам не помогает? Вы изучали только для чтенияRichTextBox
?FlowDocument
для сложных текстов макета? Я согласен с @John о StringBuilder.2. TextBlock помогает мне, но занимает слишком много памяти из-за почти 10000 текстовых блоков, и мне нужно так много, потому что у каждого из них разное положение.
3. Не поймите меня неправильно, возможно, внешний вид всего элемента управления можно изменить с помощью стилей, но я никогда не пробовал. Итак, я хочу задать еще один вопрос: могу ли я получить этот внешний вид, если применю стиль к кнопке? Элементы управления медиаплеером ps. кнопки на картинке сделаны путем объединения нескольких эллипсов и контуров.
Ответ №1:
Проверьте AvalonEdit
Также не уверен, как вы храните строки, но использовали ли вы StringBuilder
раньше?
Комментарии:
1. Проверьте код, который я опубликовал. Я не уверен, как поможет StringBuilder?
Ответ №2:
Вот мой код (немного измененный):
public class SimpleTextBlock : FrameworkElement
{
#region Static
private const double _fontSize = 12;
private static Point _emptyPoint;
private static Typeface _typeface;
private static LinearGradientBrush _textBrush;
public readonly static DependencyProperty TextWidthProperty;
static SimpleTextBlock()
{
_emptyPoint = new Point();
_typeface = new Typeface(new FontFamily("Sergoe UI"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
GradientStopCollection GSC = new GradientStopCollection(2);
GSC.Add(new GradientStop(Color.FromArgb(160, 255, 255, 255), 0.0));
GSC.Add(new GradientStop(Color.FromArgb(160, 180, 200, 255), 0.7));
_textBrush = new LinearGradientBrush(GSC, 90);
_textBrush.Freeze();
SimpleTextBlock.TextWidthProperty = DependencyProperty.Register(
"TextWidth",
typeof(double),
typeof(SimpleTextBlock),
new FrameworkPropertyMetadata(0.0d, FrameworkPropertyMetadataOptions.AffectsRender));
}
#endregion
FormattedText _formattedText;
public SimpleTextBlock(string text)
{
_formattedText = new FormattedText(text, System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight, _typeface, _fontSize, _textBrush);
}
public SimpleTextBlock(string text, FlowDirection FlowDirection)
{
_formattedText = new FormattedText(text, System.Globalization.CultureInfo.InvariantCulture, FlowDirection, _typeface, _fontSize, _textBrush);
}
protected override void OnRender(DrawingContext drawingContext)
{
_formattedText.MaxTextWidth = (double)GetValue(TextWidthProperty);
drawingContext.DrawText(_formattedText, _emptyPoint);
}
public double TextWidth
{
get { return (double)base.GetValue(TextWidthProperty); }
set { base.SetValue(TextWidthProperty, value); }
}
public double ActualTextWidth
{
get { return _formattedText.Width; }
}
public double ActualTextHeight
{
get { return _formattedText.Height; }
}
}
Комментарии:
1. Хотя этот код хорош, я думаю, что люди (включая меня) задавались вопросом, зачем вам нужно 10 000 текстовых блоков в одном представлении. Похоже, что существует фундаментальная проблема с тем, как выкладывается страница. Вы смотрели
FlowDocuments
? Не могли бы вы приложить снимок экрана или рисунок того, как выглядит программа, чтобы мы могли помочь вам определить наилучший курс действий2. У меня еще нет SS, но я хочу создать медиа-библиотеку с поиском, что-то вроде библиотеки в WindowsMediaPlayer. Я ничего не знаю о FlowDocuments, но я намерен посмотреть на это.
3. Почему бы не использовать стилизованный
ListBox
илиDataGrid
?4. Я использовал ListBox, но он выглядит так плохо, и я не знаком со стилизацией какого-либо компонента, поэтому я создаю свой собственный. Я думаю, что проще создать свой собственный элемент управления, который я могу изменить в любое время, чем научиться использовать тот, который уже существует. Можете ли вы опубликовать мне какой-либо код, объясняющий, как использовать стили? Стилизованный ListBox будет хорош, как и любой другой.
Ответ №3:
Поскольку, похоже, мы решили, что вам следует стилизовать элемент управления, подобный listbox, вот несколько примеров различных действий, которые вы можете сделать:
Используйте изображения в качестве элементов
Честно говоря, все зависит от того, как вы хотите, чтобы это выглядело. WPF хорош тем, насколько он контролирует, как что-то выглядит.
Безумный пример использования listbox для создания орбит планеты