0

Below is View code of my project. Actually when Help button is clicked, it opens new window. As I didn't have access to Window object, I had to write it in Back-end code of View part, which MVVM don't prefer. Is there any way by which I can strictly follow MVVM and open new window from View-Model part of my code? If yes how? Because I need access of new window there.

VehicleForm.xaml

<Window x:Class="Seris.VehicleForm"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="VehicalForm" Height="500" Width="650"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">


<WrapPanel Orientation="Vertical" Margin="10 " >

    <Label Content="Vehical No" HorizontalAlignment="Left"/>
    <TextBox Name="VehicalNo_Text" Height="23" Width="80" TextWrapping="Wrap" Text="{Binding VehicleNo_Focus, UpdateSourceTrigger=LostFocus}"  HorizontalAlignment="Left" />

    <Label Name="VehicleNoError_Label" Foreground="Red" Content="{Binding VehicleNo_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="186"/>

    <Label Content="Model" HorizontalAlignment="Left"/>
    <TextBox Name="Model_Text" Height="24" Width="80" TextWrapping="Wrap" Text="{Binding Model, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" />
    <Label x:Name="ModelError_Label" Foreground="Red" Content="{Binding Model_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="186"/>

    <Label Content="Manufacturing Date" HorizontalAlignment="Left"/>
    <DatePicker Name="ManufacturingDate_DateTime" SelectedDate="{Binding ManufacturingDate, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="136"/>
    <Label Name="ManufacturingDateError_Label" Foreground="Red" Content="{Binding ManufacturingDate_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="136"/>

    <Label Content="IU No" HorizontalAlignment="Left"/>
    <TextBox Height="23" Width="80" Name="IUNO_Text" TextWrapping="Wrap" Text="{Binding IUNo, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left"/>
        <Label Name="IUError_Label" Foreground="Red" Content="{Binding IU_Error, UpdateSourceTrigger=PropertyChanged}" Height="36" Width="186"/>

    <Label Content="Personnel" HorizontalAlignment="Left"/>
    <ComboBox x:Name="Personnel_Combo" SelectedValue="{Binding PersonnelNameSelected, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding PersonnelName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Width="126"/>

    <Separator Height="20" RenderTransformOrigin="0.5,0.5" Width="16"/>

    <Button Name="Save_Button" Command="{Binding SaveButton_Command}" Content="Save" Width="66"/>
    <Button Name="Replace_Button" CommandParameter="replace" IsEnabled="{Binding isEnableReplaceButton, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Command="{Binding ReplaceButton_Command}" Content="Replace" Width="66"/>
    <Button Name="Remove_Button" CommandParameter="replace" IsEnabled="{Binding isEnableReplaceButton, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Command="{Binding RemoveButton_Command}" Content="Remove" Width="66"/>


    <Label x:Name="Error_Label" Content="{Binding ErrorMessage, UpdateSourceTrigger=PropertyChanged}" Foreground="Red" HorizontalAlignment="Left" Height="41" Width="137"/>

    <ListView Name ="Grid" Height="294" Width="371" >
        <DataGrid Name="DG" ItemsSource="{Binding ListItems, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedRow, Mode=TwoWay}" GridLinesVisibility="None" IsReadOnly="True" AutoGenerateColumns="False" BorderThickness="0">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Vehical No" Binding="{Binding VehicalNo}"/>
                <DataGridTextColumn Header="Model" Binding="{Binding Model}" />
                <DataGridTextColumn Header="ManufacturingDate" Binding="{Binding ManufacturingDate}" />
                <DataGridTextColumn Header="IUNo" Binding="{Binding IUNo}" />
                <DataGridTextColumn Header="Personnel" Binding="{Binding PersonnelNameSelected}" />
                <DataGridTextColumn Header="Unique No" Binding="{Binding UniqueNo}"/>
            </DataGrid.Columns>
        </DataGrid>
    </ListView>

    <TextBlock Name="Preview" Text="{Binding EditText, UpdateSourceTrigger=PropertyChanged}"/>

    <ProgressBar Name="Progressbar" Minimum="0" Maximum="100" Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}" Height="11"/>
    <TextBlock Text="{Binding ElementName=Progressbar, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center"/>

    <Button Name="Help" Visibility="{Binding HelpVisibility, UpdateSourceTrigger=PropertyChanged}" CommandParameter="help" Height="50" Width="50" Click="Help_Click" HorizontalAlignment="Right">
        <Image Height="45" Width="45" Source="../Images/help.jpg" HorizontalAlignment="Left"/>
    </Button>

</WrapPanel>

</Window>

VehicleForm.xaml.cs

using Seris.ViewModels;
using Seris.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Seris
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class VehicleForm : Window
{
    public VehicleForm()
    {
        this.DataContext = new VehicleMainViewModel();
        this.Show();
        InitializeComponent();
    }

    private void Help_Click(object sender, RoutedEventArgs e)
    {
        Help helpWindow = new Help();
        helpWindow.Show();
    }

}
}
Pratik
  • 161
  • 4
  • 13
  • 2
    Have a search around, this question has been asked a few times. Maybe here will help? http://stackoverflow.com/questions/16652501/open-a-new-window-in-mvvm – Michael B Aug 06 '14 at 08:25
  • there are a couple of things you can do - use behaviors, use some kind of service/message-bus, etc. you are really asking for opinions here – Random Dev Aug 06 '14 at 08:25
  • If you are using PRISM in addition to MVVM look for the Window/Region adapter. – Jammer Aug 06 '14 at 08:30
  • Can I use inline DataContext property if I need to change only for specific TextBox? – Pratik Aug 06 '14 at 08:55
  • Question Michael links to has the proper answer: provide a service that can create windows (optionally allowing to select in what region) for any view/viewmodel you pass it – stijn Aug 06 '14 at 08:57

1 Answers1

0

I think you should ask yourself why you are using MVVM and what you want it to do for you, what problems it's going to solve/avoid. Don't do MVVM just because you're supposed to.

I don't think it's wrong to use code-behind in this case. The purpose of MVVM is not to have the shortest possible .xaml.cs file.

The purposes are:

  • Testability of the view logic (VM), without needing to involve a view.
  • Separation of concerns: The view defines the user interface, the view model defines a mediator between the the user interface and your business logic, through its bindings, converters etc. The ViewModel does not need to know about the View, and they can be developed separately.

Are you missing either of these purposes by opening a window in the code behind?

  • Testability: What are you supposed to test? A call to "Show()"?
  • Separation of concerns: I would argue you get a better separation opening the window in your code-behind instead of the VM knowing about the new window in any way. If the new window should have some detail of the master datacontext as datacontext, your VM should supply it as a property.
Mårten Thurén
  • 149
  • 1
  • 13
  • Its always better to achieve pure MVVM structure having Loose Coupling. – Pratik Aug 07 '14 at 00:54
  • That's not really an argument though. I would argue that the authors first solution is not less MVVM. Do you disagree with this, and if so, why is that bad design? Never follow rules you don't understand the purpose of. – Mårten Thurén Aug 07 '14 at 07:00
  • Marten Thuren: This would clear your doubts. http://stackoverflow.com/questions/6421372/why-to-avoid-the-codebehind-in-wpf-mvvm-pattern – Pratik Aug 07 '14 at 08:50