0

I'm using Catel in my application. I have any questions regarding DataObjects and ViewModels - what is the best way to use Catel efficientlu?

Scenario 1:

I have a MainViewModel and a MainView. In this View I call another View (DataWindow) with a own ViewModel (SettingsViewModel) and show it in a Dialog. In this Dialog I insert some SettingsValues and store it in xml. Last but not least I have a DataObject class to store the data from the Dialog. Here any pseudocode:

MainViewModel : ViewModelBase
{
        private void OnSystemSettingsCommandExecute()
        {
            //create a new ViewModel and show as Dialog
            uiVisualizerService.ShowDialog(new SystemSettingsViewModel());
        }

    ...
}

SystemSettingsViewModel : ViewModelBase
{
        /// <summary>
        /// Gets or sets the property value.
        /// </summary>
        [Model]
        public SettingsDataObject SettingsData
        {
            get { return GetValue<SettingsDataObject>(SettingsDataProperty); }
            set { SetValue(SettingsDataProperty, value); }
        }

        /// <summary>
        ///
        /// </summary>
        public static readonly PropertyData SettingsDataProperty =   RegisterProperty("SettingsData", typeof(SettingsDataObject));


       /// <summary>
        /// It is right to define the property again here?
        /// </summary>
        [ViewModelToModel("SettingsData")]
        public string UserName
        {
            get { return GetValue<string>(UserNameProperty); }
            set { SetValue(UserNameProperty, value); }
        }

        /// <summary>
        /// Register the UserName property so it is known in the class.
        /// </summary>
        public static readonly PropertyData UserNameProperty = RegisterProperty("UserName", typeof(string));


        // Load and Save right here?
        protected override bool Save()
        {
            SettingsData.Save(@"D:\Projects\Testdata\xml\Settings.xml");

            return true;
        }

        protected override void Initialize()
        {
            SettingsData = SavableModelBase<SettingsDataObject>.Load(@"D:\Projects\Testdata\xml\Settings.xml", SerializationMode.Xml);  
        }
}


 public class SettingsDataObject : SavableModelBase<SettingsDataObject>
 {
        // Propertys 
        /// <summary>
        /// Gets or sets the property value.
        /// </summary>
        public string UserName
        {
            get { return GetValue<string>(UserNameProperty); }
            set { SetValue(UserNameProperty, value); }
        }

        /// <summary>
        /// Register the UserName property so it is known in the class.
        /// </summary>
        public static readonly PropertyData UserNameProperty = RegisterProperty("UserName", typeof(string), "MyUserName");
 }
  1. Is it right that I must define the property "UserName" in the DataClass and in the ViewModel class? Is that the "normal way" that I define my Model property in the ViewModel and than i access my data propertys with [ViewModelToModel("SettingsData")]?
  2. How I can Load and Save automatic my Data Objects? In my case I override the "Save" and the "Initialize" methode? Is there a better way to do this in Catel?
  3. Now I must have access of the SettingsDataObject in the MainViewModel but i didn't find a way to use the object in other ViewModels. What is the "best practices" to load the settings in other ViewModels?
Mike G
  • 4,232
  • 9
  • 40
  • 66

1 Answers1

0

Question 1)

Yes, this is "right", but totally depends on the form of MVVM you want to follow. For more information, read this. I like to protect my model (make it private on the VM) and only expose the properties I really want being exposed on the VM. But some other people like to directly bind on the model instead. It's just the different number of interpretations like you can read in the article.

Question 2)

Overriding the Initialize and Save are exactly meant for this, so you are doing it the right way!

Question 3)

When you need to share a model, you can either use nested user controls to pass the model from one view model to another. If you need to access the model in a lot of different places, it might be wise to register it in the ServiceLocator. It can then automatically be injected into your view models by Catel.

// Somewhere in your code
var serviceLocator = ServiceLocator.Default;
serviceLocator.RegisterType<ISettings>(mySettings);

// Your view model constructor
public MyViewModel(ISettings mySettings)
{
  // injected here
}

If you want to create your own view model, you can do this:

var dependencyResolver = this.GetDependencyResolver();
var viewModelFactory = dependencyResolver.Resolve<IViewModelFactory>();
var viewModel = viewModelFactory.CreateViewModel<MyViewModel>(null);

Note that if you are inside another VM, you can of course let the IViewModelFactory be injected so you only need 1 line of code to create the view model.

Geert van Horrik
  • 5,689
  • 1
  • 18
  • 32
  • it might be wise to register it in the ServiceLocator. It can then automatically be injected into your view models by Catel. – user2910295 Oct 23 '13 at 09:12
  • Do you have a example? – user2910295 Oct 23 '13 at 09:12
  • ok, interesting, but should the ViewModel implement the interface "ISettings" or the "DataSettingsObject"? In this interface are only the getter for the "public SettingsDataObject SettingsData", correct? – user2910295 Oct 23 '13 at 11:02
  • No need to implement any of that. Just define the constructor with the arguments and Catel will take care of it for you. See https://catelproject.atlassian.net/wiki/display/CTL/Dependency+injection for more information. – Geert van Horrik Oct 23 '13 at 11:17
  • SettingsDataObject mySettings = new SettingsDataObject(); var serviceLocator = ServiceLocator.Default; serviceLocator.RegisterType(); – user2910295 Oct 23 '13 at 12:33
  • and than i create the MainViewModel "new MainViewModel(mySettings)" and insert the mySettings? – user2910295 Oct 23 '13 at 12:34