2

MVVMを使用してWPFプロジェクトに取り組んでおり、テーマを動的に変更する機能を実装しようとしています。テーマ情報は、個別のxamlファイル(つまり、Theme1.xaml、Theme2.xaml)にあります。さまざまな理由から、View.xamlのコードビハインドファイルではなく、ViewModelクラスで実際のテーマを変更したいと思います。

私はいくつかのアイデアを試しましたが、何も機能しません:

  • ViewのResourceDictionaryをViewModelの変数にバインドしようとしましたが、ResourceDictionaryタイプのSourceプロパティにバインドを設定できないと言われました

  • ViewModelクラスに「UpdateTheme」メソッドを呼び出すような種類のViewオブジェクトがありません

ViewクラスのMergedDictionary参照をViewModelクラスから変更する方法に関するアイデアはありますか?

ありがとう!

4

3 に答える 3

4

私はここで以前に同じ時間の問題に取り組んできましたが、私の場合はそれがあなたを助けることができるかもしれません。

すべてのテーマファイル(theme1.xaml、theme2.xaml ...)をexeパスのThemesフォルダーにコピーします。以下のサンプルコードを試してみてください。バインディングの使用

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>
于 2012-06-21T13:45:48.357 に答える
2

私はこのようにアプリケーションで起動時にテーマの切り替えを処理します。

Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(Themes.Where(p => p.Value.ThemeName == "MyTheme").SingleOrDefault().Value.Theme);

まず、をクリアしDictionariesてプリセットを削除しますTheme。これは、エディターでデフォルトのテーマを使用run-timeし、ユーザーの構成に応じて切り替え中に使用するためです。

アプリケーションを再起動して新しいテーマをロードしますが、状態などを保存すると、アプリケーションを完全に再起動しなくてもViewModel、をリロードできるはずです。UIしかし、これは私のプロジェクトの要件ではなかったので、私はそれほど遠くまで行きませんでした。

おそらく、からテーマの名前を渡してから、からのViewロジックを使用して解析することができますViewModel

于 2012-06-21T13:25:50.477 に答える
1

問題は、ViewModelから直接ビューを変更しようとしていることです。これは許可されていません。プロパティバインディングに基づいた、よりパッシブなソリューションを考え出す必要があります。

私のアプローチは、メインビューのコードビハインドでマージされたディクショナリのリソースファイルを切り替える小さなコードを使用することです。これを行う方法は、バインドされているViewModelのプロパティの値によって識別できます。MVVMでは、ビュー中心の動作をサポートするための少量のコードビハインドが許可されています。

于 2012-06-21T13:25:29.503 に答える