Where do you put global variables in a WPF application?

17,900

Solution 1

Globals? just say no. (sorry, someone had to say it) for config stuff, as suggested by others, use the App.Config,
The code you provided looks like a M-V-VM to me--you should check it out. WPF, by it's nature, promotes this. Learn it, love it, live it.

Solution 2

I consider the sort of global state that I think you're describing to be configuration information. Resultantly, I place it in the App.config file, generally through the project's properties' "Settings" tab.

This will expose your configuration information through <WhateverNamespace>.Properties.Settings where it's easy to access in a typesafe manner.

If you're describing something else, such as mutable application state that isn't configuration information, I'd strongly suggest shifting your paradigm to a more client-application form where such global state is strongly frowned upon due to it's error-prone nature. IE, restructure your application model so that it doesn't depend on global data-- use parameters and objects instead.

Solution 3

Try this

  /// <summary>
    /// "Global variables" or kind of "Session State" class.
    /// To save a variable: ApplicationState.SetValue("currentCustomerName", "Jim Smith");
    /// To read a variable: MainText.Text = ApplicationState.GetValue<string>("currentCustomerName");
    /// </summary>
    public static class ApplicationData
    {
        /// <summary>
        /// Get an application-scope resource Formatted News
        /// </summary>
        /// <returns></returns>
        public static DataContainerModel GetNews()
        {
            var  formattedNews = (DataContainerModel)Application.Current.Resources["FormattedNews"];
            return formattedNews;
        }

        /// <summary>
        /// Set an application-scope resource Formatted News
        /// </summary>
        /// <param name="dataContainerModel"></param>
        public static void SetNews(DataContainerModel dataContainerModel)
        {
            Application.Current.Resources["FormattedNews"] = dataContainerModel;
        }

        private static ConcurrentDictionary<string, object> _values = new ConcurrentDictionary<string, object>();

        public static void SetValue(string key, object value)
        {
            if (_values.ContainsKey(key))
            {
                var oldValue = new object();
                _values.TryRemove(key, out oldValue);
            }
            _values.TryAdd(key, value);
        }

        public static T GetValue<T>(string key)
        {
            if (_values.ContainsKey(key))
            {
                return (T)_values[key];
            }
            else
            {
                return default(T);
            }
        }

    }

So here you see two approaches. I would like to have both of them.

Oh! DataContainerModel is going to be any custom class you need.

Share:
17,900
Angry Dan
Author by

Angry Dan

web/software developer, .NET, C#, WPF, PHP, software trainer, English teacher, have philosophy degree, love languages, run marathons my tweets: http://www.twitter.com/edward_tanguay my runs: http://www.tanguay.info/run my code: http://www.tanguay.info/web my publications: PHP 5.3 training video (8 hours, video2brain) my projects: http://www.tanguay.info

Updated on June 05, 2022

Comments

  • Angry Dan
    Angry Dan almost 2 years

    In PHP web programming, I always made a singleton Output object in which I could put global information that had to be available from any line of code.

    So in WPF applications, I create the following class to perform the same function, e.g. the variable ReturnToPageIdCode returns the page to which another page is supposed to return to after processing some task, and I can set and get that value anywhere I want.

    This works nicely.

    However, I can't help to think that in the stateful WPF environment, I'm recreating the wheel with this singleton Output object.

    Where do you put hold application-wide values in your WPF applications? Is there some standard place to do this?

    public class Output
    {
        private Output output;
    
        private static Output instance;
    
        public string ReturnToPageIdCode { get; set; }
    
        public static Output GetInstance()
        {
            if (instance == null)
            {
                instance = new Output();
            }
            return instance;
        }
    
        public string GetTestMessage()
        {
            return "This is a global test message from the output singleton.";
        }
    }