Как добавить зависимость в общий интерфейс в низкоуровневый установщик стилей WPF? - PullRequest
0 голосов
/ 19 марта 2020

Мне нужно, чтобы зависимости вводили интерфейс в мои низкоуровневые установщики стилей для основных элементов WPF, таких как Label, TextBlock и т. Д. c. Я не могу понять, как.

Настройки для таких вещей, как FontSize, Размер кнопки, цвета и т. Д. c. Я использовал их для хранения в общем файле настроек WPF (файл .RESX) в общей сборке. Я мог бы сослаться на него в любом файле XAML в любой другой сборке, используя {x:Static}: Например:

<Style x:Key="TitleTextBlockStyle" TargetType="{x:Type TextBlock}">
    <Setter Property="FontSize" 
            Value={Binding Source={x:Static coreModule:Properties.Settings.Default}, 
                           Path=FontSizeTitle}"/>

</Style>

Но это игнорировало подход DI, который я уже использовал, поэтому я попытался переместить все настройки в зависимость интерфейс Вот так (но представьте себе еще много свойств):

public interface ISettings
{
    int FontSizeTitle { get; set; }
}

Это хорошо на более высоком уровне, когда у меня есть одна из моих собственных моделей просмотра, удобная. Но мой TextBlockStyle находится на самом низком уровне моего ResourceDictionary включает. Он не может полагаться на общий тип данных Datacontext. Так что же мне делать в моем стиле?

Мой обходной путь - XAML MarkupExtension, который завершает все вокруг и получает интерфейс ISettings в любом месте XAML:

<Style x:Key="TitleTextBlockStyle" TargetType="{x:Type TextBlock}">
    <Setter Property="FontSize" 
            Value="{Binding Source={coreModule:Settings}, 
                            Path=FontSizeTitle}"/>
</Style>

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

namespace CoreModule.Extensions
{
[MarkupExtensionReturnType(typeof(ISettings))]
public class SettingsExtension : MarkupExtension
{   
    public SettingsExtension() { }

    // HACK: Just assume that the one and only app implements
    // the ISettings interface we need:

    public override object ProvideValue(IServiceProvider serviceProvider) =>
        Application.Current as ISettings;

}}

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

Так как же Я делаю это "правильно"? Есть ли какой-нибудь лучший подход, который на самом деле работает с контейнером DI, чтобы позволить мне писать низкоуровневые стили с внедренным интерфейсом?

...