WPF 和 MVVM - 动态改变主题

标签 wpf mvvm

我正在使用 MVVM 开发一个 WPF 项目,我正在尝试实现一个动态更改主题的功能。主题信息位于单独的 xaml 文件中(即 Theme1.xaml、Theme2.xaml)。出于各种原因,我想在 ViewModel 类中而不是在 View.xaml 的代码隐藏文件中进行实际的主题更改。

我已经尝试了几个想法,但无法让任何东西发挥作用:

  • 我尝试将 View 的 ResourceDictionary 绑定(bind)到 ViewModel 中的一个变量,但被告知无法在 ResourceDictionary 类型的 Source 属性上设置绑定(bind)

  • 我的 ViewModel 类中没有任何类型的 View 对象可以调用“UpdateTheme”方法

关于如何从 ViewModel 类更改 View 类中的 MergedDictionary 引用,有什么想法吗?

谢谢!

最佳答案

我之前在这里处理过同样的时间问题,我在我的案例中所做的可能会帮助你。

将所有主题文件(theme1.xaml、theme2.xaml...)复制到 exe 路径下的 Themes 文件夹中。并尝试使用以下示例代码。使用绑定(bind)

C#:

private void ChangeTheme(FileInfo _SelectTheme)
{
    App.Current.Resources.Clear();
    App.Current.Resources.Source = new Uri(_SelectTheme.FullName, UriKind.Absolute);
}
private ObservableCollection<FileInfo> _files;
public ObservableCollection<FileInfo> Files
{
    get { return _files; }
    set { _files = value; OnChanged("Files"); }
}
public MainWindow()
{
    this.InitializeComponent();

    Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
    {
        var localthemes = new System.IO.DirectoryInfo("Themes").GetFiles();
        if (Files == null)
            Files = new ObservableCollection<FileInfo>();
        foreach (var item in localthemes)
        {
            Files.Add(item);
        }
        SelectedTheme = Files[0];
    }));

    this.DataContext = this;
}

public event PropertyChangedEventHandler PropertyChanged;
public void OnChanged(string name)
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(name));
}

XAML:

<Window x:Class="WPFTheme.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="Window"
        Title="MainWindow"
        Width="640"
        Height="480">

    <Grid x:Name="LayoutRoot" Background="{DynamicResource DisabledForegroundBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.285*" />
            <ColumnDefinition Width="0.365*" />
            <ColumnDefinition Width="0.35*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.132*" />
            <RowDefinition Height="0.162*" />
            <RowDefinition Height="0.403*" />
            <RowDefinition Height="0.168*" />
            <RowDefinition Height="0.135*" />
        </Grid.RowDefinitions>
        <Button Width="57"
                Margin="15,13,0,10.872"
                HorizontalAlignment="Left"
                Content="Enabled" />
        <Button Width="72"
                Margin="0,14,17.12,10.872"
                HorizontalAlignment="Right"
                Content="Disabled"
                IsEnabled="False" />
        <TextBlock Grid.Column="1"
                   Width="69"
                   Margin="11.88,15,0,27.872"
                   HorizontalAlignment="Left"
                   Text="TextBlock"
                   TextWrapping="Wrap" />
        <TextBox Grid.Column="1"
                 Width="64"
                 Height="21"
                 Margin="9.88,0,0,4.872"
                 HorizontalAlignment="Left"
                 VerticalAlignment="Bottom"
                 Text="TextBox"
                 TextWrapping="Wrap" />
        <TextBox Grid.Column="1"
                 Height="21"
                 Margin="88.88,0,35.8,3.872"
                 VerticalAlignment="Bottom"
                 IsEnabled="False"
                 Text="TextBox Disabled"
                 TextWrapping="Wrap" />
        <CheckBox Grid.Row="1"
                  Width="71"
                  Height="14"
                  Margin="11,7.128,0,0"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top"
                  Content="CheckBox" />
        <CheckBox Grid.Row="1"
                  Width="71"
                  Height="14"
                  Margin="0,8.128,15.12,0"
                  HorizontalAlignment="Right"
                  VerticalAlignment="Top"
                  Content="Disabled"
                  IsEnabled="False" />
        <ComboBox Grid.Column="2"
                  Width="94"
                  Margin="8.2,18,0,11.872"
                  HorizontalAlignment="Left"
                  ItemsSource="{Binding Files}"
                  SelectedItem="{Binding SelectedTheme,
                                         Mode=TwoWay,
                                         UpdateSourceTrigger=PropertyChanged}" />
        <ComboBox Grid.Column="2"
                  Width="94"
                  Margin="0,17,14,12.872"
                  HorizontalAlignment="Right"
                  IsEnabled="False"
                  ItemsSource="{Binding Files}" />
        <DataGrid Grid.Row="2"
                  Grid.Column="1"
                  Margin="8.88,6.876,7.8,62.862"
                  AutoGenerateColumns="True"
                  ItemsSource="{Binding Files}" />
        <DatePicker Grid.Row="2"
                    Height="23"
                    Margin="10,0,15,147"
                    VerticalAlignment="Bottom" />
        <GroupBox Grid.Row="2"
                  Grid.Column="2"
                  Margin="6.2,2.876,6,5.862"
                  Header="GroupBox">
            <ScrollViewer Margin="6,0.723,1,1" ScrollViewer.HorizontalScrollBarVisibility="Visible">
                <ListBox Width="161"
                         Height="108"
                         ItemsSource="{Binding Files}" />
            </ScrollViewer>
        </GroupBox>
        <ListView Grid.Row="2"
                  Grid.Column="1"
                  Height="59"
                  Margin="12.88,0,5.8,-4.138"
                  VerticalAlignment="Bottom"
                  ItemsSource="{Binding Files}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="File Name">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Name}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
        <ProgressBar x:Name="progressBar"
                     Grid.Row="1"
                     Grid.Column="1"
                     Height="20"
                     Margin="5.88,6.128,61.8,0"
                     VerticalAlignment="Top"
                     Value="50" />
        <RadioButton Grid.Row="1"
                     Width="64"
                     Margin="11,25.128,0,29.124"
                     HorizontalAlignment="Left"
                     Content="RadioButton" />
        <RadioButton Grid.Row="1"
                     Width="51"
                     Margin="0,25.128,33.12,29.124"
                     HorizontalAlignment="Right"
                     Content="RadioButton"
                     IsEnabled="False" />
        <Slider Grid.Row="1"
                Grid.Column="1"
                Margin="11.88,34.128,38.8,15.124"
                AutoToolTipPlacement="BottomRight"
                Maximum="{Binding Maximum,
                                  ElementName=progressBar}"
                Minimum="{Binding Minimum,
                                  ElementName=progressBar}"
                Value="{Binding Value,
                                ElementName=progressBar}" />
        <TabControl Grid.Row="1"
                    Grid.Column="2"
                    Margin="7.2,9.128,9,0.124">
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5" />
            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5" />
            </TabItem>
        </TabControl>
        <TreeView Grid.Row="3"
                  Margin="8,5.138,12.12,1.79"
                  ItemsSource="{Binding Files}" />
        <ToolBar Grid.Row="4"
                 Grid.ColumnSpan="2"
                 Margin="10,9.21,104.8,17">
            <Button />
            <CheckBox />
            <ComboBoxItem />
            <MenuItem />
            <Separator />
            <TabItem />
        </ToolBar>
    </Grid>
</Window>

关于WPF 和 MVVM - 动态改变主题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11139103/

相关文章:

wpf - MVC/MVP/MVVM 什么鬼?

wpf - 在scrollviewer wpf中禁用鼠标滚轮滚动

c# - 在单元测试中使用 WPF Dispatcher 的正确方法

c# - WPF Datagrid 鼠标双击编辑单元格

WPF 圆角文本框

c# - 如何从大文本中提取匹配字符串?

c# - 使用 Prism - WPF 关闭动态添加的选项卡项

c# - 当属性设置为值时禁用行选择数据网格 WPF

c# - 根据 ViewModel 类型为 ItemsControl 选择 DataTemplate

c# - 如何在 MVVM 中将 ObservableCollection 从 ViewModelA 传递到 ViewModelB