views:

425

answers:

4

I am building a settings dialog for my application and right now all of the settings correspond with settings on the main view-model, but as I add more view's and view-models some may not.

I need to know what the best practice is for loading the current settings into the settings dialog and then saving the settings to thier corresponding view-models if the user clicks okay.

I will not be using the Properties.Settings.Default system to store settings since I want my application to be as portable as possible and this would store user scoped settings in the directory: C:\Users\ username \Local Settings\Application Data\ ApplicationName Instead of in my application's directory.

In case it makes any difference I am using the MVVM Light Toolkit by Laurent Bugnion.

+1  A: 

You could use MEF, exporting a settings view from each view model and importing them as a list of views that you add to a stack panel or some such in your main settings view.

A good source of info of using MEF is: http://mef.codeplex.com/wikipage?title=Guide

Here is a sample program I meant to get up sooner:

using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.Reflection;

namespace zTestConsole
{
    public interface ISimple
    {
        string Message { get; }
    }

    [Export("SimpleHello",typeof(ISimple))]
    public class SimpleHello : ISimple
    {
        [Export("Message")]
        public string Message
        {
            get { return "Silverlight rocks!"; }
        }
    }

    [Export("SimpleBello",typeof(ISimple))]
    public class SimpleBello : ISimple
    {
        [Export("Message")]
        public string Message
        {
            get { return "C# rocks!"; }
        }
    }

    public class SimpleMultiCat
    {
        [ImportMany("Message")]
        public IEnumerable<string> Messages { get; set; }
    }

    public class SimpleCat
    {
        [Import("SimpleHello")]
        public ISimple simple { get; set; }
    }

    class Program
    {
        private static CompositionContainer container;

        static void Main(string[] args)
        {

            AggregateCatalog catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));

            SimpleMultiCat cats = new SimpleMultiCat();
            SimpleCat cat = new SimpleCat();

            Program.container = new CompositionContainer(catalog);

            try
            {
                Program.container.ComposeParts(cats);

                foreach (string message in cats.Messages)
                {
                    Console.WriteLine(message);
                }
            }
            catch (CompositionException ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.WriteLine();

            try
            {
                container.ComposeParts(cat);
                Console.WriteLine(cat.simple.Message);
            }
            catch (CompositionException ex)
            {
                Console.WriteLine(ex.ToString());
            }

        }
    }
}
Felan
+2  A: 

I recently posted an article that discussed about developing Silverlight apps in MVVM pattern. I mentioned several approaches and best-practice to work with dialog box in a MVVM application. Check out http://tinyurl.com/383odnm for details.

Hope this helps.

James
+1  A: 

How about implementing that with the Messenger of the toolkit?

When changes are made in the Settings ViewModel you just inform anyone interested:

Messenger.Send<Settings>(changedSettings);

And all Viewmodels which need to know if settings have been changed register to that message:

Messenger.Register<Settings>(this, delegate(Settings changedSettings){loadSettings(changedSettings);});

Have a read here: Mvvm light messenger or check this similar post mvvm-light-how-to-access-property-in-other-view-model

CodeWeasel
Don't forget to check if the receiver is still valid in the delegate. There will be a time period between closing the view and the next GC. In this time period you will still receive changed settings messages but the view is gone.
adrianm
Does this address the need, down the road, of some settings not corresponding to the main view model settings?I read that as a need for extensibility which is why I suggest using MEF.
Felan
Felan: Every model registering for messages of the type Settings will receive sent settings. So you are not limited to the main view model. But you wouldn't send different settings for different view models. But you could also do that by sending different Settings classes...I haven't had a closer look to MEF yet but it sure is a solution. :)Perhabs you should show a tailored example to clarify your solution. :)
CodeWeasel
CodeWeasel: I'm a little swamped, probably for the next couple of weeks yet, but when I get more time to fiddle with it I will see about a better tailored example. The main problem I thought Justin was asking about was bringing divergent settings from other modules into one settings dialog. Ideally this wouldn't require the settings dialog to detailed knowledge of every module (in theory different users could have different modules even). It could be I have misunderstood though.
Felan
I understood Justin having a settings object and when its edited in a global settings view he wants to share the information with the other views. Thats why I suggested the messenger. But I guess you could also use them together. MEF for loading the different settings classes and use the messenger to spread them after update.
CodeWeasel
+1  A: 

I've had this problem also. Solution for me was to have something like an ISettingsService Model. There would be 2 implementations. One for the real service and one mocked that was used for design time and unit testing.

An example here: http://compiledexperience.com/blog/posts/Blendable-MVVM-Dependency-Injection-and-Unit-Testing

vidalsasoon