Значение Propety стиля привязки в ResouceDictionary к свойствам ViewModel - PullRequest
0 голосов
/ 15 октября 2019

Я пытаюсь изменить стиль моего WPF-приложения (FontFamily, FontSize и т. Д.). Поиск SO не увенчался успехом. В приложении я использую MVVM Pattern. Чтобы придать приложению одинаковый вид, я использую ресурсы для определения различных стилей и скинов. Это работает до сих пор. То, что я хочу понять, - это изменение отдельных свойств по времени выполнения с использованием окна стилей:

    <Window x:Class="StyleResourceDictionariesDemo.View.StyleWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="StyleWindow" Height="450" Width="800"
        Style="{DynamicResource WindowStyle}">
    <Window.Resources>
        <ResourceDictionary Source="../ResourceDictionaries/Styles/Controls/WindowStyle.xaml"/>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <TextBlock Height="20" Width="75" Text="FontFamily:" Margin="10" TextAlignment="Right"/>
            <ComboBox x:Name="CbFonts" Width="200" Margin="10,10,7,0"
                      ItemsSource="{Binding Source={x:Static Fonts.SystemFontFamilies}}" SelectedItem="{Binding OwnFontFamily, UpdateSourceTrigger=PropertyChanged}"
                      SelectedValuePath="Source" Height="23" VerticalAlignment="Top">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" FontFamily="{Binding}" Height="20"/>
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
        </StackPanel>
        <Border Height="2" Width="Auto" Background="Red" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
        <StackPanel Orientation="Horizontal"  HorizontalAlignment="Left">
            <TextBlock Height="20" Width="50" Text="Size:" Margin="10" TextAlignment="Right"/>
            <Slider Style="{DynamicResource SliderStyle}" Width="100" x:Name="FontSizeSlider" Value="{Binding OwnFontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    Minimum="{Binding OwnSmallFontSize}" Maximum="{Binding OwnBigFontSize}" TickPlacement="Both" Margin="10" TickFrequency="{Binding OwnFontSizeSteps}" IsSnapToTickEnabled="True"/>
            <TextBlock Height="20" Width="50" Text="{Binding ElementName=FontSizeSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}" TextAlignment="Right"/>
        </StackPanel>
    </StackPanel>
</Window>

со следующей прикрепленной моделью представления:

using System.Windows.Media;

namespace StyleResourceDictionariesDemo.ViewModel
{
  class StyleWindowViewModel : ViewModelBase
  {
    #region Variables
    private double _ownFontSize = 12, _ownSmallFontSize = 8, _ownBigFontSize = 16;
    private FontFamily _ownFontFamily = new FontFamily("Arial");
    #endregion

    #region Properties
    public double OwnFontSizeSteps { get; } = 4;
    public FontFamily OwnFontFamily
    {
      get => _ownFontFamily;
      set
      {
        _ownFontFamily = new FontFamily(value.Source);
        OnPropertyChanged(nameof(OwnFontFamily));
      }
    }


    public double OwnFontSize
    {
      get => _ownFontSize;
      set
      {
        _ownFontSize = value;
        OnPropertyChanged(nameof(OwnFontSize));
      }
    }
    public double OwnSmallFontSize
    {
      get => _ownSmallFontSize;
      set
      {
        _ownSmallFontSize = value;
        OnPropertyChanged(nameof(OwnSmallFontSize));
      }
    }
    public double OwnBigFontSize
    {
      get => _ownBigFontSize;
      set
      {
        _ownBigFontSize = value;
        OnPropertyChanged(nameof(OwnBigFontSize));
      }
    }
    #endregion

    #region Constructor
    public StyleWindowViewModel()
    {

    }
    #endregion


  }
}

Кроме того, я создал файл xaml ControlBaseStyle изкоторый наследует каждый другой стиль:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   xmlns:viewModel="clr-namespace:StyleResourceDictionariesDemo.ViewModel">
    <viewModel:StyleWindowViewModel x:Key="StyleWindowViewModel" />
    <Style TargetType="{x:Type Control}" x:Key="ControlBaseStyle">
        <Style.Setters>
            <Setter Property="FontFamily" Value="{DynamicResource OwnFontFamily}"/>
            <Setter Property="FontStyle" Value="{DynamicResource FontStyleKey}"/>
            <Setter Property="FontWeight" Value="{DynamicResource FontWeightKey}"/>
            <Setter Property="FontSize" Value="{DynamicResource OwnFontSize}"/>
            <Setter Property="Background" Value="{DynamicResource SystemBackground}"/>
            <Setter Property="Foreground" Value="{DynamicResource SystemForeground}"/>
        </Style.Setters>
    </Style>
</ResourceDictionary>

Проблема, с которой я столкнулся, заключается в том, что controlbasestyle не распознает изменения из свойств ViewModel, и в настоящее время я не понимаю, почему. Может быть, я упустил что-то простое, я просто не вижу, или я использую неправильный подход, чтобы решить эту проблему?

Заранее спасибо.

Мирко

РЕДАКТИРОВАТЬ 1:

Моя цель - изменить стили и скины во время выполнения. Структура выглядит следующим образом: Изначально все стили присваивают различные свойства скином. Скин определяет цвета, шрифт, размер и другие вещи, которые должны быть согласованы в приложении. Они могут быть вызваны их определенным именем (определенным с помощью x: key). Стиль извлекает значение, определенное над скином, используя имя для используемого в данный момент сеттера (например, Value = -DynamicResource SystemBackground-для фона свойства). Пока все хорошо.

Цель состоит в том, чтобы сделать это с помощью шаблона MVVM. Я определил окно стиля и ViewModel (код выше). Но я не могу заставить стиль заметить это изменение.

Первый вопрос: могу ли я и если да, то как мне изменить значение для FontFamily (или любого другого свойства) во время выполнения. Второй вопрос: будет ли этот подход правильным в реальной жизни или есть лучшие подходы?

Пример скина:

LightSkin.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ResourceDictionary.MergedDictionaries>
        <!--Default Style-->
        <ResourceDictionary Source="../00_Default/DefaultStyle.xaml"/>

        <!--Specific Style-->
        <ResourceDictionary Source="LightColor.xaml"/>
        <ResourceDictionary Source="LightSizes.xaml"/>
        <ResourceDictionary Source="LightFont.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

DefaultStyle.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="../../Styles/Controls/ButtonStyle.xaml"/>
    <ResourceDictionary Source="../../Styles/Controls/LabelStyle.xaml"/>
    <ResourceDictionary Source="../../Styles/Controls/ToggleButtonStyle.xaml"/>
    <ResourceDictionary Source="../../Styles/Controls/WindowStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>

LabelBaseStyle.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ControlBaseStyle.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <Style TargetType="{x:Type Label}" x:Key="LabelBaseStyle" BasedOn="{StaticResource ControlBaseStyle}">
        <Style.Setters>
            <Setter Property="Width" Value="300"/>
            <Setter Property="Height" Value="150"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Top"/>
            <Setter Property="Content" Value="{Binding Content}"/>
        </Style.Setters>
    </Style>
</ResourceDictionary>

Каждый(Базовый) Стиль наследуется прямо или косвенно из ControlBaseStyle.xaml (код выше).

1 Ответ

1 голос
/ 15 октября 2019

Вы должны связать установщики ControlBaseStyle со свойствами модели представления:

<viewModel:StyleWindowViewModel x:Key="StyleWindowViewModel" />
<Style TargetType="{x:Type Control}" x:Key="ControlBaseStyle">
    <Style.Setters>
        <Setter Property="FontFamily" Value="{Binding OwnFontFamily, Source={StaticResource StyleWindowViewModel}}"/>
        ...
    </Style.Setters>
</Style>

Также убедитесь, что вы установили свойства фактического StyleWindowViewModelэкземпляр, который вы определили в ResourceDictionary, когда хотите изменить стиль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...