0

I am beginner and have an issue in setting a WPF project and following MVVM pattern; I do not see how to link the view to the viewmodel with the organization below :

I have set 3 folders : Model, View and ViewModel, both at the root of the project named "Company.App.UI". The App.xaml and MainWindow.xaml are at the root of the project.

Starting with this, I want control the content displayed in the client area of the MainWindow by : - having the rendered views in the folder 'View' as UserControls, for example 'LoginView.xaml' - having the corresponding view model in the folder 'ViewModel', for example 'LoginView.xaml.cs'

Then what I did in MainWindow.xaml is :

<Window x:Class="Company.App.UI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewmodel="clr-namespace:Company.App.UI.ViewModel"
        xmlns:view="clr-namespace:Company.App.UI.View" <!-- does not work, not a namespace -->
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type viewmodel:LoginViewModel}">
            <view:LoginView/> <!-- does not work -->
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Orientation="Horizontal">
            <ContentControl Content="{Binding ClientArea}"/>
        </StackPanel>
    </Grid>        
</Window>

And in MainWindow.xaml.cs :

using System.Windows;
using System.Windows.Controls;
using Company.App.UI.ViewModel;

namespace Company.App.UI
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    private UserControl _ClientArea = null;

    public UserControl ClientArea
    {
      get { return _ClientArea; }
      set { _ClientArea = value; }
    }

    public MainWindow()
    {
      if (_ClientArea == null) { ClientArea = new LoginViewModel(); }
      InitializeComponent();
    }
  }
}

The LoginView is a simple UserControl with one Label just to see it is what it is. If I put my LoginView.xaml at the root of the project, next to MainWindow.xaml, it works ... What am I doing wrong / missing ? I do not want to use any frameworks (PRISM and so on) for getting this to work. My apologies if my post is a duplicate but I have also fail to find it while searching. Thanks,

Update

I use VS2013 with 0 updates / patches / etc. Everything is in the same project.

The errors output is :

  1. The type or namespace name 'View' does not exist in the namespace 'Company.App.UI' (are you missing an assembly reference?)
  2. The name "LoginView" does not exist in the namespace "clr-namespace:Company.App.UI.View".
  3. The type 'view:LoginView' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built.

LoginView.xaml :

<UserControl x:Class="Company.App.UI.ViewModel.LoginViewModel"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Label>User control login</Label>
    </Grid>
</UserControl>

LoginViewModel.cs :

using System.Windows.Controls;

namespace Company.App.UI.ViewModel
{
  public partial class LoginViewModel : UserControl
  {
    public LoginViewModel()
    {

    }
  }
}
Minuqx
  • 1
  • 2
  • Folder structure isn't relevant. You have to use appropriate namespace declarations in your code files, e.g. `namespace Company.App.UI.View { ... }` – Clemens Jun 12 '17 at 13:51
  • 1
    *"it works"* - what doesn't work? Do you want [to improve](https://codereview.stackexchange.com/) working code? – Sinatr Jun 12 '17 at 13:51
  • `ClientArea` is declared as `UserControl` (very bad idea). Then you assign something called `LoginViewModel` to it. What is `LoginViewModel`? Is it a viewmodel or a control? – 15ee8f99-57ff-4f92-890c-b56153 Jun 12 '17 at 13:53
  • To bind to a property of the window instead of a property of the window's `DataContext` (which you leave null), use a relative source/ancestor type binding: `Content="{Binding ClientArea, RelativeSource={RelativeSource AncestorType=Window}}"` – 15ee8f99-57ff-4f92-890c-b56153 Jun 12 '17 at 13:54
  • If you're struggling with MVVM it might be worth looking at this https://www.tutorialspoint.com/mvvm/ – Gareth Jun 12 '17 at 13:56
  • 1
    Basic rule to remember. Your ViewModel musn't use `System.Windows.Controls;` namespace. – FCin Jun 12 '17 at 13:58
  • If `namespace:Company.App.UI.View` is not a namespace, is it in a different project? If it's in a different project, you need to specify `assembly` in the `xmlns` attribute. – 15ee8f99-57ff-4f92-890c-b56153 Jun 12 '17 at 14:00
  • Try adding `` to your data template? – FakeCaleb Jun 12 '17 at 14:03
  • @FakeCaleb There is exactly one element in the data template. That element is the user control. – 15ee8f99-57ff-4f92-890c-b56153 Jun 12 '17 at 14:12
  • One of the principles of MVVM is to separate view and application logic (viewModel). You're mixing things making your view model inherit from a view related object and putting a what you call LoginViewModel into a ui object. A framework (I suggest MVVMCross) helps you to understand the components of the pattern, their relations, behaviours and responsabilities. – Antonello G. Bianchi Jun 12 '17 at 14:59

3 Answers3

0

In LoginView.xaml change this:

x:Class="Company.App.UI.ViewModel.LoginViewModel"   

to this

x:Class="Company.App.UI.ViewModel.LoginView"

because this is a control not a ViewModel

Also, this is how the LoginView.xaml.cs should look like (didn't see your implementation):

using System.Windows.Controls;

namespace Company.App.UI.View
{
    /// <summary>
    /// Interaction logic for LoginView.xaml
    /// </summary>
    public partial class LoginView : UserControl
    {
        public LoginView()
        {
            InitializeComponent();
        }
    }
}

when you will get the hang of it (mvvm) I would recommend using the mvvm light toolkit for the plumbing (there is no need to reinvent the wheel)

slugster
  • 49,403
  • 14
  • 95
  • 145
igorc
  • 2,024
  • 2
  • 17
  • 29
0

Exactly .... Do whatever changes Igor has told you . along with that ,

Change your MainWindow.xaml.cs

 if (_ClientArea == null) { ClientArea = new LoginViewModel(); }

to

 if (_ClientArea == null) { ClientArea = new LoginView(); }

Also as per my understanding you just want to display one lable from user control to main window and want to study MVVM concept. So here is the explaination for your example which may help you

 <Grid>
        <!--connect to viewmodel-->
        <Grid.DataContext>
         <viewmodel:LoginViewModel></viewmodel:LoginViewModel>
        </Grid.DataContext>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!--import user control-->
        <view:LoginView Grid.Row="0"></view:LoginView>

        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <ContentControl Content="{Binding ClientArea}"/>
        </StackPanel>

    </Grid>

Note - Try to keep zero code in any of code behind . Thats the main purpose of MVVM . It should just have

  • Model ...(class file which should have purely just proprties )
  • View ...(usercontrols, xaml,window file which should contain just
    xaml code with zero code behind)
  • Modelview... (class file which should contain purely connection between view and model, which should not contain any object of view or model.It connects through the binding)

also i dont know for what purpose you created 'ClientArea' ... Did you define its content somewhere?
Let me know if you need any help... I have some sample demo projects on MVVM.

Lina
  • 163
  • 13
0

Post with similar purpose that also helped me to get things :

Binding a ContentControl to UserControl, and reuse same instance,

with the excellent topic within here : How to preserve the full state of the View when navigating between Views in an MVVM application?.

Another good point to start I found after I post my question (...) : https://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx

Basically what I want to achieve is to manage the content area within one single window and whithout any framework and more precisely manage "transactions", that is switching from one screen to another upon user interaction.

Thanks for all the comments, things are getting clearer.

Minuqx
  • 1
  • 2