This project is read-only.

Save user selected appearance as default value for next start-up

Aug 15, 2013 at 12:11 PM
Hi,

Firstly: this is a beautiful library. Awesome to work with. I do have one question though: how do I keep the user selected style (light/dark) and accent colour for when the application starts up next? (on application close all selected preferences are lost).

What I have thought of is to create a setting in something like app.config. Updating the value in app.config is the easy part. How do I retrieve it so that the resource dictionary source in App.xaml gets its value from the setting?
Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
                <ResourceDictionary Source={__This is the value i want to read from app.config__}/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
Any assistace would be greatly appreciated.

Thank you in advance
Aug 15, 2013 at 7:10 PM
I don't think that it will work this way. But have a look at the demo app, the place where appearance is changes. You can see which values will be changed. And you can save these values and restore at program start.
Aug 15, 2013 at 7:56 PM
I have this working in my application using the clients registry. In my app file I have
        protected override void OnStartup(StartupEventArgs e)
        {
            #if DEBUG
            #else
            try
            {
                AppearanceManager.Current.AccentColor = (Color)ColorConverter.ConvertFromString(_registry.ReadKey(Helpers.Registry._Color));
                AppearanceManager.Current.FontSize = (_registry.ReadKey(Helpers.Registry._FontSize).ToString() == "large") ? FontSize.Large : FontSize.Small;
                AppearanceManager.Current.ThemeSource = new System.Uri(_registry.ReadKey(Helpers.Registry._Theme), UriKind.Relative);
            }
            catch { }
            #endif
        }
For my Registry helper class I have chopped down of course
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tracker.Helpers
{
    class Registry
    {
        #region Constant Variables
        private const string _Root = "Software";
        private const string _Publisher = "Publisher Here";
        private const string _Application = "Application Name Here";
        #endregion Constant Variables

        #region Static ApplicationKeys for registry
        /// <summary>
        /// Key to pull the users color settings
        /// </summary>
        public static readonly ApplicationKeys _Color = new ApplicationKeys { Name = "Color", Encrypted = false };
        /// <summary>
        /// Key to pull the users font size setting
        /// </summary>
        public static readonly ApplicationKeys _FontSize = new ApplicationKeys { Name = "FontSize", Encrypted = false };
        /// <summary>
        /// Key to pull the theme from the users settings
        /// </summary>
        public static readonly ApplicationKeys _Theme = new ApplicationKeys { Name = "Theme", Encrypted = false };
        #endregion Static ApplicationKeys for registry

        #region global vars
        string _objResult;
        #endregion

        /// <summary>
        /// Reads and returns a keys value
        /// </summary>
        /// <param name="KeyName">Keyname to read</param>
        /// <returns>string value</returns>
        public string ReadKey(ApplicationKeys keyName)
        {
            // Use RegistryKey object to open the 32 bit version of HKLM
            using (RegistryKey HKCU = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default))
            {
                try // Wrapped in the event a key does not exist
                {
                    // Use RegistryKey object to open the node to the application keys
                    using (RegistryKey subKey = HKCU.OpenSubKey(_Root).OpenSubKey(_Publisher).OpenSubKey(_Application))
                    {
                        // result value to raw key value
                        _objResult = subKey.GetValue(keyName.Name).ToString();
                    }
                }
                catch { }
            }

            return _objResult;
        }

        /// <summary>
        /// Writes our values for the application but excludes DB
        /// </summary>
        /// <param name="keyName"></param>
        /// <param name="value"></param>
        public void WriteKey(ApplicationKeys keyName, string value)
        {
            using (RegistryKey HKCU = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default))
            {
                try
                {
                    using (RegistryKey subKey = HKCU.OpenSubKey(_Root).OpenSubKey(_Publisher).OpenSubKey(_Application, true))
                    {
                            subKey.SetValue(keyName.Name, value);
                    }
                }
                catch { }
            }
        }

        /// <summary>
        /// Class to hold the key values to reference back to the registry.
        /// </summary>
        public class ApplicationKeys
        {
            /// <summary>
            /// Name of the registry key
            /// </summary>
            public string Name { get; set; }
        }
    }
}
This is the change I have made in my SettingsApperanceViewModel
        public Link SelectedTheme
        {
            get { return this.selectedTheme; }
            set
            {
                if (this.selectedTheme != value)
                {
                    this.selectedTheme = value;
                    _registry.WriteKey(Helpers.Registry._Theme, value.Source.ToString());
                    OnPropertyChanged("SelectedTheme");

                    // and update the actual theme
                    AppearanceManager.Current.ThemeSource = value.Source;
                }
            }
        }

        public string SelectedFontSize
        {
            get { return this.selectedFontSize; }
            set
            {
                if (this.selectedFontSize != value)
                {
                    this.selectedFontSize = value;
                    _registry.WriteKey(Helpers.Registry._FontSize, value);
                    OnPropertyChanged("SelectedFontSize");

                    AppearanceManager.Current.FontSize = value == FontLarge ? FontSize.Large : FontSize.Small;
                }
            }
        }

        public Color SelectedAccentColor
        {
            get { return this.selectedAccentColor; }
            set
            {
                if (this.selectedAccentColor != value)
                {
                    this.selectedAccentColor = value;
                    _registry.WriteKey(Helpers.Registry._Color, value.ToString());
                    OnPropertyChanged("SelectedAccentColor");

                    AppearanceManager.Current.AccentColor = value;
                }
            }
        }
Aug 16, 2013 at 1:08 PM
@chromefor: Please don't spam other discussions with request for help. Thanks.
@kozw: Are you able to delete these requests (including my answer here)? They are very useless for the discussions they were put.
Aug 18, 2013 at 8:29 PM
@felixdd: done, thanks for the headsup
Aug 19, 2013 at 3:22 PM
@felixdd: Thank you. it does make sense. looking at the way in which AppearanceManager.Current... is used, it would then be possible to write values to app.config when they change by means of the OnChange event. ApprearanceManager can then be used when the app is started to restore the last selected settings.

Thank you Lebowsker. I cannot unfortunately assume that the user will have admin rights to the pc running the app and therefore might not be able to make any changes to the registry :-)
Sep 2, 2013 at 7:15 PM
n0c0ntr0L you can save values to your settings, and load them in app.xaml at startup back.
Sep 3, 2013 at 8:09 AM
Hi nukec

Thank you very much. That will do the trick!