如何使主题选择器应用更改应用程序

时间:2016-01-30 15:29:53

标签: c# wpf themes

我正在尝试创建一个togglebutton,它会将应用程序主题更改为在按下时适合移动设备。这是一个特殊的皮肤,只会改变一些东西,如边距,字体大小和最小/宽度。这不应该删除我设置的其他样式。

我能够让按钮工作,但更改仅适用于当前窗口。如何更改此代码以使其适用于整个应用程序?

搜索我发现使用“Application.Current.Resources.MergedDictionaries”可能是要走的路,但我不知道如何合并它。

本网站的信息是基础。 http://svetoslavsavov.blogspot.com/2009/07/switching-wpf-interface-themes-at.html

以下是主题选择器的代码。

public class ThemeSelector : DependencyObject
{

    public static readonly DependencyProperty CurrentThemeDictionaryProperty =
        DependencyProperty.RegisterAttached("CurrentThemeDictionary", typeof(Uri),
        typeof(ThemeSelector),
        new UIPropertyMetadata(null, CurrentThemeDictionaryChanged));

    public static Uri GetCurrentThemeDictionary(DependencyObject obj)
    {
        return (Uri)obj.GetValue(CurrentThemeDictionaryProperty);
    }

    public static void SetCurrentThemeDictionary(DependencyObject obj, Uri value)
    {
        obj.SetValue(CurrentThemeDictionaryProperty, value);
    }

    private static void CurrentThemeDictionaryChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (obj is FrameworkElement) // works only on FrameworkElement objects
        {
            ApplyTheme(obj as FrameworkElement, GetCurrentThemeDictionary(obj));
        }
    }

    private static void ApplyTheme(FrameworkElement targetElement, Uri dictionaryUri)
    {
        if (targetElement == null) return;

        try
        {
            ThemeResourceDictionary themeDictionary = null;
            if (dictionaryUri != null)
            {
                themeDictionary = new ThemeResourceDictionary();
                themeDictionary.Source = dictionaryUri;

                // add the new dictionary to the collection of merged dictionaries of the target object
                targetElement.Resources.MergedDictionaries.Insert(0, themeDictionary);
            }

            // find if the target element already has a theme applied
            List<ThemeResourceDictionary> existingDictionaries =
                (from dictionary in targetElement.Resources.MergedDictionaries.OfType<ThemeResourceDictionary>()
                 select dictionary).ToList();

            // remove the existing dictionaries 
            foreach (ThemeResourceDictionary thDictionary in existingDictionaries)
            {
                if (themeDictionary == thDictionary) continue;  // don't remove the newly added dictionary
                targetElement.Resources.MergedDictionaries.Remove(thDictionary);
            }
        }
        finally { }
    }
}

以下是togglebutton代码隐藏的内容。

    private void MobileTheme_Click(object sender, RoutedEventArgs e)
    {
        if ((sender as ToggleButton).IsChecked.Value)
        {
            ThemeSelector.SetCurrentThemeDictionary(this, new Uri("/MobileSkin.xaml", UriKind.Relative));
        }
        else
        {
            ThemeSelector.SetCurrentThemeDictionary(this, new Uri("/ClassicSkin.xaml", UriKind.Relative));
        }
    }

1 个答案:

答案 0 :(得分:1)

有效的新代码:

public class ThemeSelector : DependencyObject
{
    public static void ApplyTheme(Uri dictionaryUri)
    {
        var targetElement = Application.Current;
        if (targetElement == null || dictionaryUri == null) return;

        try
        {
            // find if the target element already has a theme applied
            var existingDictionaries =
                (from dictionary in targetElement.Resources.MergedDictionaries.OfType<ThemeResourceDictionary>()
                 select dictionary).ToList();

            // remove the existing dictionaries 
            foreach (var thDictionary in existingDictionaries)
            {
                targetElement.Resources.MergedDictionaries.Remove(thDictionary);
            }

            // add the new dictionary to the collection of merged dictionaries of the target object, needs to be added to the end to overwrite the other items
            targetElement.Resources.MergedDictionaries.Add(new ThemeResourceDictionary { Source = dictionaryUri });
        }
        finally { }
    }
}

切换按钮:

    private void MobileTheme_Click(object sender, RoutedEventArgs e)
    {
        if ((sender as ToggleButton)?.IsChecked.Value == true)
        {
            ThemeSelector.ApplyTheme(new Uri("/MobileSkin.xaml", UriKind.Relative));
        }
        else
        {
            ThemeSelector.ApplyTheme(new Uri("/ClassicSkin.xaml", UriKind.Relative));
        }
    }