Мой обычный способ сделать это с помощью ItemsControl, вы можете заменить панель на WrapPanel, а шаблон элемента на TextBlock, содержащий все ваши привязки:
<ItemsControl ItemsSource="{Binding Elements}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}">
<TextBlock.Foreground>
<SolidColorBrush Color="{Binding Foreground}" />
</TextBlock.Foreground>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Затем вернувшись в свою модель представления, вы можетесделать что-то вроде этого:
public class MainViewModel
{
public TextElement[] Elements { get; } = new TextElement[]
{
new TextElement{ Text="Hello World! "},
new TextElement{ Text="This is some blue text!", Foreground=Colors.Blue }
};
}
public class TextElement
{
public string Text { get; set; }
public Color Foreground { get; set; } = Colors.Black;
}
Результаты:
![enter image description here](https://i.stack.imgur.com/fXS9P.png)
Очевидно, что если вы хотите динамический документ, то вы заменитеTextElement[]
с ObservableCollection<TextElement>
и добавлением INPC и т. Д.
Это более тяжело, чем добавление прогонов и пролетов и т. Д., Но с положительной стороны вы можете заменить шаблон элемента на типизированные DataTemplates в блоке ресурсов.который позволяет вам легко встраивать графику или что-либо еще, что вам нужно.
Единственный способ, которым мне удалось этого добиться, - это универсальное пользовательское поведение, которое привязывается к ObservableCollection и управляет дочерними элементами GUI вручную.