M
M
Michael2015-06-07 14:10:16
WPF
Michael, 2015-06-07 14:10:16

How to write in MVVM?

Please tell me how to properly use the MVVM pattern in a WPF application. Example classes:
Using a control in a third-party class (Creating from code):

BrowserView someBrowser = new BrowserView();
  container.Children.Add(someBrowser);
  someBrowser.Navigate("http://google.ru/");
  someBrowser.SomeControlText = "Перешёл на сайт google.ru";

view class:
public partial class BrowserView : UserControl
  {
    BrowserViewModel viewModel;
    public BrowserView()
    {
      InitializeComponent();
      viewModel = new BrowserViewModel(this.GetType());
      this.DataContext = viewModel;
    }
    
        public string SomeControlText
        {
            get { return viewModel.Model.SomeControlText; }
            set { viewModel.Model.SomeControlText = value; }
        }
    
        public void Navigate(string newAddress)
        {
            viewModel.Model.SomeBrowser.Address = newAddress;
        }
  }

XAML:
<UserControl x:Class="GPClient.View.BrowserView">
    <Grid x:Name="BrowserContainer">
      <ContentControl Content="{Binding Path=Model.SomeBrowser}"></ContentControl>
    </Grid>
    <SomeControl Text="{Binding Path=Model.SomeControlText}" />
  </UserControl>

ViewModel class:
public class BrowserViewModel : Notifier
    {
        public BrowserModel Model { get; private set; }
        public BrowserViewModel(Type typeControl)
        {
            Model = new BrowserModel();
      
            ChromiumWebBrowser browser = new ChromiumWebBrowser();
            Model.SomeBrowser = browser;
        }
    }

Model class:
public class BrowserModel : Notifier
    {
        ChromiumWebBrowser someBrowser;
        public ChromiumWebBrowser SomeBrowser
        {
            get { return someBrowser; }
            set { someBrowser = value; OnPropertyChanged("SomeBrowser"); }
        }
    
        string someControlText;
        public string SomeControlText
        {
            get { return someControlText; }
            set { someControlText = value; OnPropertyChanged("SomeControlText"); }
        }
    }

There are a couple of specific questions:
1) Let's say I want to change the Text property of SomeControl.
This property is bound to Model.SomeControlText.
How to do it right?
- There is an option to make the viewModel public and access it like this:
someBrowser.viewModel.Model.SomeControlText = "какой-то текст";

- There is an option to duplicate this property in the ViewModel (while also making the viewModel public) and do it like this:
someBrowser.viewModel.SomeControlText = "какой-то текст";

- Another option is to create a property in the View and do something like this:
public string SomeControlText
        {
            get { return viewModel.Model.SomeControlText; }
            set { viewModel.Model.SomeControlText = value; }
        }

Address like this: The question is which of these options is correct and if none, how is it done? 2) I want to change the Address property of the ChromiumWebBrowser object in the ViewModel. There are the same options as in the previous question. And how to do it right? What am I doing wrong? Or is everything right?
someBrowser.SomeControlText = "какой-то текст";

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
Roman, 2015-06-07
@Sing303

To get started, take some kind of MVVM framework (SimpleMVVM, MVVMLight, they have a bunch of examples), make your own view, ViewModel. In these frameworks, the base classes for creating a VM are already implemented (INotyfyPropertyChanged is implemented). In the VM, you need to add the necessary properties with which the properties of the elements will be bound. It is also desirable to make a service class that will create a model on demand, register an instance of the class in App.Resources, and bind the necessary VM immediately in Xalm, to DataContext="{Binding GroupsViewModel, Mode=OneWay, Source={StaticResource Locator}} "> (the locator has a GroupsViewModel property, in which the necessary VM is created, all parameters are passed to services (for example, working with a database).
Creating and passing elements, or working with controls directly, increases code cohesion, and so on.
those for example in your case:
locator.cs

public class Locator
{
  public MainViewModel MainVM 
  {
      get {return new MainViewModel(); }
  }
}

MainViewModel.cs
public class MainViewModel : Notifier
    {
       MainViewModel ()
       {
       }

        string address;
        public string Address;
        {
            get { return address; }
            set { address = value; OnPropertyChanged("Address"); }
        }

        string someControlText;
        public string SomeControlText
        {
            get { return someControlText; }
            set { someControlText = value; OnPropertyChanged("SomeControlText"); }
        }
    }

in App.xaml we prescribe in resources (of course we add the necessary xmlns)
MainView.xaml
<UserControl x:Class="GPClient.View.BrowserView" DataContext="{Binding MainViewModel, Source={StaticResource Locator}}">>
    <ChromiumWebBrowser Address="{Binding Path=Address, Mode=TwoWay}"/>
    <SomeControl Text="{Binding Path=SomeControlText, Mode=TwoWay}" />
  </UserControl>

It's all about Mode=TwoWay. if the element itself sets the property, then it is automatically updated in the VM, and vice versa, if you need to go to the address, in the method in the VM we write Address = " http://go-to.site "; we refer to the VM field, and not to the private member, otherwise PropertyChanged will not be called, with SomeText, as well.
If we have a TextBox, then the binding in this way allows us to receive the value entered into it.
to bind methods, and events, use Command and triggers in XAML.
You have a bit confused the concept of ViewModel and Model. The VM specifies the properties to which the View elements will be bound, and the Model is the data we work with, for example, the database model, the classes into which XML is serialized.
Download MVVMLight, SimpleMVVM, they are simple frameworks with good examples and lightweight.

B
Boris the Animal, 2015-06-23
@Casper-SC

If relevant, then I can show an example with the MvvmLight library.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question