Что именно вы здесь пытаетесь разобрать? В вашем тексте говорится, что вы пытаетесь проанализировать XAML, но код, который вы указали, - HTML?
Если вы можете придерживаться XAML, то это относительно просто. Прежде всего вам понадобятся некоторые данные XAML в вашей модели представления:
public string[] Spans { get; } = new string[]
{
"<Span Foreground=\"Blue\">Hello World!</Span>",
"<Span Foreground=\"Green\">Goodbye World!</Span>"
};
Всякий раз, когда у вас есть список вещей для рисования в WPF, вы обычно используете ItemsControl. Однако вместо списка вам, вероятно, понадобится WrapPanel. Конвертер можно использовать для преобразования каждого элемента списка в диапазон, который вы можете заключить в родительский ContentControl:
<ItemsControl ItemsSource="{Binding Spans}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=., Converter={StaticResource SpanConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Тогда все, что вам нужно, - это сам конвертер, чтобы получить необработанный XAML, разобрать его и вернуть полученный объект. Вам также нужно добавить пространство имен по умолчанию (пустое) вместе с "x", чтобы анализатор знал, где найти объекты, которые он десериализует:
public class SpanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var context = new ParserContext();
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
return XamlReader.Parse(value?.ToString(), context) as ContentElement;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
Результат:
Теперь возьмите все это и выбросьте, потому что синтаксический анализ необработанного XAML не , как вы делаете это в MVVM. Чтобы сделать это правильно, вы должны создать модель представления для ваших отрезков следующим образом:
public class SpanViewModel
{
public string Text { set; get; }
public Color Foreground { set; get; }
// .. plus any other fields you want
}
И вместо этого вы создадите их список:
public SpanViewModel[] Spans { get; } = new SpanViewModel[]
{
new SpanViewModel{Text="Hello World!", Foreground=Colors.Blue},
new SpanViewModel{Text="Goodbye World!", Foreground=Colors.Green}
};
Мы собираемся использовать DataTemplate, поэтому избавьтесь от ItemTemplate из ItemsControl:
<ItemsControl ItemsSource="{Binding Spans}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
и создайте DataTemplate для SpanViewModel, привязав к соответствующим свойствам (вам нужно использовать TextBlock, потому что Span не поддерживает привязку ):
<Window.Resources>
<DataTemplate DataType="{x:Type local:SpanViewModel}">
<TextBlock Text="{Binding Text}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="{Binding Foreground}" />
</Setter.Value>
</Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</Window.Resources>
Существует множество вариантов, но этого должно быть достаточно, чтобы начать работу.