question

scottthomson-6985 avatar image
0 Votes"
scottthomson-6985 asked ·

Multiple Window (Views/ViewModels) Generation Strategy

I am using C#, .Net WPF and MVVM approach

What would be a recommended strategy/Design for the situation were I have a MainWindow view and associated viewmodel and wish to "open" another such window for the user which will display another objects values. For example they are viewing an objects values via mainwindow then go into a search feature where they find another object for which they want to view its values. they click on this in the list and a view appears showing that objects values. they then can close this view and return to the original view with the original object.

First I have at least 2 choices Im aware of I can begin with. Use the existing MainWindow view and viewmodel for the new object as they are exactly the same or 99% same and need to use same view/viewmodel functionality or write a (almost) copy of the mainwindow view/viewmodel and show this one. The second option will require more maintenance because I have to duplicate any changes across both but can make other things easier and maybe cleaner.

So whats best approach for this issue?

The next decision to make is how to do this? I have so far considered the following ways to do the "showing" of the new view and selected objects data.;
1. set up datatemplates in the mainwindow and swap the views in and out (ie triggered by xaml button command bound to viewmodel)
2. instantiate a new instance of MainWindow view and mainwindowviewmodel using .ShowDialog in code (ie triggered by xaml button command bound to viewmodel)
4. Set up a view factory instead of instantiating in code

In all cases I need to pass a parameter to the newly shown View or Dialog that is used by its ViewModel to retrieve from database and show the required object.

thanks Scott




windows-wpf
· 5
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@scottthomson-6985
What does your search feature where they find another object for which they want to view its values refer to? Is it something like Row detaills in DataGrid? Where do shown object values in? In this Window or a new Window? Please give me more description for what you want to implement.


1 Vote 1 ·

the search feature is another window containing row details (which are a list of records in the database) in datagrid. one column contains a button that user clicks to open a new window (this is the subject of my question) showing that record (or object) values. after user has viewed these values and possibly changed them they close this window and return to the search window. once they close the search window they then return to the original mainwindow.

1 Vote 1 ·

DaisyTian I have several mvvmlight messages used to coordinate object used for their datacontext between the 7 views that are in the mainwindow. If I use the strategy of creating a duplicate of the mainwindow and mainwindowviewmodel I will have to also duplicate all the 7 (sub)views or do things like use tokens etc to target only the duplicated version of the mainwindow as I would expect that my oringial mainwindow thats still open in the background could pickup these messages and act on them as well.

0 Votes 0 ·

DaisyTian there is one way I can do it I think using a new instance of the MainWindow which is by passing a parameter to the new instance (created via .ShowDialog), however I get an error which I suspect is a nullexception error in the Views code behind constructor. I think the error arises because the there is no parameter passed to the constructor so the parameter is un-initialised at this point. I was planning on sending the searchIDs parameter when i instantiate a new instance of the MainWindow (code inserted in next reply because this website imposes a ridiculous 100 char limit). I could then use the values in searchIDs to do a call to database and retrieve the record to show in the viewmodel. BUT I get a weird error somehwere near the InitializeComponent(); line. When I remove the parameter from the code then this error does not occur. Is there a problem due to the searchIDs parameter not yet be initialised or being null when you insert a parameter in the windows constructor?

0 Votes 0 ·
         private void OpenChemical()
         {
             SearchID searchids = new SearchID();
             searchids.IDAssessment = SelectedReport.IDAssessment;
             searchids.IDChemical = SelectedReport.IDChemical;
             MainWindow searchwindow = new MainWindow(searchids);
             searchwindow.ShowDialog();
         }
    
 public partial class MainWindow : Window
 {
     public MainWindow(SearchID SearchIDs)
     {
         InitializeComponent();
 
         this.RootWindow.DataContext = new MainWindowViewModel(SearchIDs);
     }

0 Votes 0 ·

1 Answer

DaisyTian-MSFT avatar image
1 Vote"
DaisyTian-MSFT answered ·

I make a demo on my understanding for your question, please check if I misunderstand. If I misunderstand, could you please give an operation result diagram to anlayze?
The ViewModel is:

 class PersonViewModel:NotifyObject
     {
         private PersonModel userEdit;
         public PersonModel UserEdit
         {
             get { return userEdit; }
             set
             {
                 userEdit = value;
                 OnPropertyChange("UserEdit");
             }
         }
    
         private ObservableCollection<PersonModel> ltPersons = new ObservableCollection<PersonModel>();
         public ObservableCollection<PersonModel> LtPersons
         {
             get { return ltPersons; }
             set
             {
                 this.ltPersons = value;
                 OnPropertyChange("LtPersons");
             }
         }
    
         public PersonViewModel()
         {
             LtPersons = new ObservableCollection<PersonModel>() { 
                 new PersonModel { Name = "John1", Age = 11, Pass=false,Email= new Uri("mailto:JOE+@school.com") }, 
                 new PersonModel { Name = "John2", Age = 12 , Pass=false,Email= new Uri("mailto:JOE+@school.com")}, 
                 new PersonModel { Name = "John3", Age = 13 , Pass=false,Email= new Uri("mailto:JOE+@school.com")} };
         }
    
         public ICommand ButtonCommand
         {
             get
             {
                 return new DelegateCommand<PersonModel>((model) => 
                 {
                     UpdateUser updateUser = new UpdateUser();
                     updateUser.DataContext = model;
                     updateUser.Show();
                 });
             }
         }           
     }

The MainWindow is:

   <Window.DataContext>
         <local:PersonViewModel></local:PersonViewModel>
     </Window.DataContext>
    
     <Grid Width="800" Height="250" HorizontalAlignment="Left" >
         <DataGrid Width="200" Height="200"
                   x:Name="dataGrid" 
                   HorizontalAlignment="Left"
                   ItemsSource="{Binding LtPersons}" 
                   AutoGenerateColumns="False"  
                   SelectionMode="Extended" 
                   SelectionUnit="FullRow" 
                   SelectedItem="{Binding UserEdit}"
                   >
             <DataGrid.Columns>
                 <DataGridTextColumn Header="Name" Width="80" Binding="{Binding Name,Mode=TwoWay}"/>
                 <DataGridTextColumn Header="Age" Width="50" Binding="{Binding Age,Mode=TwoWay}" />
             </DataGrid.Columns>
         </DataGrid>
         <Button Height="18" Width="50" Content="Query" Command="{Binding ButtonCommand}" CommandParameter="{Binding UserEdit}" />
     </Grid>

The UpdateWindow is:

  <Grid >
         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="100"/>
             <ColumnDefinition Width="*"/>
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="300"/>
         </Grid.RowDefinitions>
         <Label Grid.Row="0" Grid.Column="0" Content="Name"  HorizontalAlignment="Right" ></Label>
         <TextBox Grid.Row="0" Grid.Column="1" Margin="4" Text="{Binding Name,Mode=TwoWay}" />
         <Label  Grid.Row="1" Grid.Column="0" Content="Age:" HorizontalAlignment="Right"/>
         <TextBox  Grid.Row="1" Grid.Column="1" Margin="4" Text="{Binding Age,Mode=TwoWay}"/>
         <Label Grid.Row="2" Grid.Column="0" Content="Mail:" HorizontalAlignment="Right"/>
         <TextBox  Grid.Row="2" Grid.Column="1" Margin="4" Text="{Binding Email,Mode=TwoWay}"/>
         <Label Grid.Row="3"  Grid.Column="0"  Content="Pass:" HorizontalAlignment="Right"/>
         <TextBox Grid.Row="3" Grid.Column="1"  Margin="4" Text="{Binding Pass,Mode=TwoWay}" />
         <Button  Grid.Row="4" Grid.Column="0" Content="Save" Click="Button_Click" ></Button>
    
     </Grid>


If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 5 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DaisyTian here is a flow diagram. Window 2 is the subject of my question. Should I use a new instance of MainWindow for Window 2 or should I build a new separate View/ViewModel for Window 2.

WIndow 2 can look and operate very similar to MainWindow so I can use MainWindow as WIndow 2 although I get problematic behaviour with the views used in MainWindow when I re-use those in a new instance. MainWindow and Window 2 based on MainWindow seem to be leaking into one another.

71733-image.png


0 Votes 0 ·
image.png (42.8 KiB)

@scottthomson-6985
Do the Winddow2 and MainWindow look like my UpdateWindow which is the third part code in my reply? What is your 'Entity 1 of 200' mean?

0 Votes 0 ·

Daisy tan entity 1 of 200 just means 1 of 200 records.

Can I ask you this way if you had a the design in the diagram would you have a separate view/view model to open and view a record in more detail or would you create a new instance of the main window or would you use a different solution?

0 Votes 0 ·

Daisy tan I don’t need to see any code. I am looking for design or strategy advice. How would this be done in the industry?

Thanks

0 Votes 0 ·
Show more comments