Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GlobalSettings ViewModel

Tags:

mvvm

wpf

settings

I have some global settings that should come from the ViewModel and should be available to all DataTemplates across all UserControls. It includes things like GlobalButtonMargin, GlobalStrokeWidth or GlobalWorkspaceBackgroundColor. Those things are in the viewmodel because the user can edit these settings at runtime.

How would you go about implementing this in a good MVVM fashion?

I thought about having a Singleton GlobalSettingsViewModel. Is this the preferred approach? If so how can I acess the singleton instance from XAML?

Another way would be to pass the GlobalSettings to all ViewModel instances that exist in my application so I can access from the viewmodels I create DataTemplates for. But that feels unclean.

A third approach would be to ditch the ViewModel approach alltogether define that as XAML resources and set the resources dynamically at runtime using FindResource.

Could you sketch out, how you would design your application to support this scenario?

like image 231
bitbonk Avatar asked Dec 02 '25 19:12

bitbonk


2 Answers

You could use a static you can read from and bind to, using the x:Static in your XAML. I do not like doing static global settings as it's more of an anti-pattern.

I think you should look into inversion of control/dependency injection. There are many IoC containers out there, but I usually use Unity for my dependency injection. It's available at http://prism.codeplex.com

Using IoC, you could register you settings class, and within your VM that need the data, they can easily pull out the settings you want. Your code would look something similar to this (if using unity).

var vm = container.Resolve<SomeViewModel>();

public class SomeViewModel
{
  public SomeViewModel(IUnityContainer container)
  {
      ISomeSettings settings = container.Resolve<ISomeSettings>();    
  }
}

EDIT: Or here is another solution you may be looking for:

Create your singleton:

class GlobalSettings : ViewModel
{
    private Thickness m_globalGirth;

    private static GlobalSettings m_instance = new GlobalSettings();

    public GlobalSettings()
    {
        GlobalGirth = new Thickness(2, 2, 2, 2);
    }
    public Thickness GlobalGirth
    {
        get { return m_globalGirth; }
        set
        {
            m_globalGirth = value;
            InvokePropertyChanged("GlobalGirth");
        }
    }

    public static GlobalSettings Instance
    {
        get { return m_instance; }
        set { m_instance = value; }
    }
}

Then setup your bindings:

<Window x:Class="WpfApplication3.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfApplication3="clr-namespace:WpfApplication3"
    Title="Window1" Height="300" Width="300" MouseDoubleClick="Window_MouseDoubleClick">
    <Window.Resources>
        <WpfApplication3:GlobalSettings x:Key="settings" />
    </Window.Resources>
    <Grid>
        <Border BorderThickness="{Binding Source={StaticResource settings}, Path=Instance.GlobalGirth}"
                BorderBrush="Black"
                Width="100"
                Height="100" />
    </Grid>
</Window>
like image 173
Jeremiah Morrill Avatar answered Dec 05 '25 00:12

Jeremiah Morrill


I would create the type to represent your ViewModel as a class and then define the instance of it as a resource at the ApplicationLevel. That guarentees a single instance for the entire application and you will now be able to refer to those settings using StaticResource. So for example:

<Application xmlns:myNS="clr-namespace:MyNamespace;assembly=MyAssembly" ...>
    <Application.Resources>
        <myNS:MySettings x:Key="Settings" />
    </Application.Resources>
</Application>

And then in windows/controls/templates/etc. you can access the MySettings instance using:

{Binding Source={StaticResource Settings}, Path=MyProperty}
like image 39
Drew Marsh Avatar answered Dec 04 '25 23:12

Drew Marsh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!