Введение
Был у меня случай, когда мне понадобилась string, которая содержала данные из ресурсов XAML в WPF, так как мне не разрешалось указывать ресурсы в string. Я сразу подумал, что, возможно, можно использовать MarkupExtension для этого, но точно не знал, как это сделать. Я провёл некоторые исследования, и я оказался не единственным, кто был заинтересован в этом вопросе. Я обнаружил, что Мартин Греч опубликовал несколько ответов, которые позволили создать строку со строковой частью, объединенной с привязкой. Его MarkupExtension имеет свойство string и свойство Binding, и это было очень просто. Я включил его код в образец для справки.
Я сразу начал работать с этим, с чем-то совершенно другим, так как мне нужно было получить ресурсы XAML, и я хотел иметь возможность иметь несколько ресурсов XAML в string. Я рассматривал наличие нескольких свойств, но решил вместо этого взять лист из того, что недавно было добавлено в C#, интерполяцию строк и использование того же формата с именами ресурсов в фигурных скобках. Я бы мог пройти и вручную извлечь имена ресурсов из строки, но понял, что RegEx лучше решит эту проблему.
Сначала я использовал «грязное» решение, используя цикл foreach, но был уверен, что это не лучший вариант, поэтому поделился кодом на codeproject и спросил, есть ли лучший способ. -*/Конечно, способов достаточно, и Ричард Деминг указал путь.
Код
Код получен из MarkupExtenson и добавляет единственное свойство для string, которая должна быть интерпретирована:
public class ConcatExtension : MarkupExtension
{
private static readonly Regex Pattern = new Regex("{([^}]+)}", RegexOptions.Compiled);
public string String { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var dep = new DependencyObject();
if (!DesignerProperties.GetIsInDesignMode(dep))
{
return Pattern.Replace(String, match =>
{
string newMatch = match.Groups[1].Value;
serviceProvider.TryProvideValue(newMatch, out object value);
return Convert.ToString(value);
});
}
return String;
}
}
Регулярное выражение используется для поиска всех экземпляров, где текст находится между двумя фигурными скобками, которые используются для указания ссылок на ресурсы. Метод RegEx Replace с MatchEvaluator используется для замены имен ресурсов и связанных с значением строки ресурса скобками.
В коде MatchEvaluator используется метод расширения TryProvideValue, который я использовал с IServiceProvider, чтобы находить ресурсы и обрабатывать ошибки, когда ресурс не найден, метод, имеющий выходной аргумент и возвращающий true, если ресурс найден. Если ресурс не найден, данные выходного аргумента о том, что ресурс с этим именем не найден и возвращает false:
public static class ExtensionMethods
{
public static bool TryProvideValue(this IServiceProvider serviceProvider, string key, out object value)
{
try
{
value = new StaticResourceExtension(key).ProvideValue(serviceProvider);
return true;
}
catch
{
value = $"{{"{key}" could not be found}}";
return false;
}
}
}
Пример
Пример представляет собой простое window с двумя элементами управления TextBlock, в Text DependencyPropery которого используется метод Concat ExtensionMethod, содержащий корректное имя ресурса в фигурных скобках:
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="15"
Text="{local:Concat String='This is a test to see if the Concat MarkupExtension really does find the resource TestString: TestString = {TestString}'}"
TextWrapping="Wrap" />
а другое — недопустимое имя ресурса в фигурных скобках.
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="15"
Text="{local:Concat String='This is a test to see what happens when the Concat MarkupExtension does not find the resource TestString: TestString = {TestString1}'}"
TextWrapping="Wrap" />
Существует только один ресурс:
<system:String x:Key="TestString">Testing</system:String>
Вот как выглядит Окно в режиме разработки:
Вот как выглядит Окно в режиме запуска:
Оригинал: codeproject.com
Автор: Лунтик