0
votes

I want to use multiple views for the same viewmodel. I can't seem to work it out. What am I doing wrong? The simple example:

The file viewmodel:

using System.IO;

namespace WpfApplicationExample.MVVM
{
    internal class FileViewModel
    {
        public FileInfo FileInfo { get; set; }
    }
}

The file list viewmodel:

namespace WpfApplicationExample.MVVM
{
    class FileListViewModel
    {
        public FileViewModel Files { get; set; }
    }
}

The file list view. This is where I try to use View.Context, but it doesn't work:

<UserControl x:Class="WpfApplicationExample.MVVM.FileListView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:cal="http://www.caliburnproject.org"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <ListView Name="Files" cal:View.Context="Details"/>
    </Grid>
</UserControl>

The file view #1: Details:

<UserControl x:Class="WpfApplicationExample.MVVM.File.Details"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel Orientation="Horizontal">
        <Label Name="FileInfo_Name"/>
        <Label Name="FileInfo_Length"/>
        <Label Name="FileInfo_Directory"/>
    </StackPanel>
</UserControl>

The file view #2, Simple:

<UserControl x:Class="WpfApplicationExample.MVVM.File.Simple"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Label Name="FileInfo_Name"/>
    </Grid>
</UserControl>

This is just a most basic idea, to show file placement and where I'm trying to put the cal:View.Context="Details"

So why it's not working?


Edit: I'm sorry, I thought I made the question easy to understand, it seems, not. Let me elaborate:

The situation I'm describing is very simple. The easiest example is Windows File Explorer. You know, how you can easily change the views: Details, List, Tiles, Small Icons, Large Icons, etc... That's it - you are displaying the same folder's content, the same file list, hence we assume, the same single viewmodel. The only thing that changes is the view that is used to display that same viewmodel. Details view, List view, etc. Same single viewmodel. Multiple different views.

Taken from Caliburn.Micro documentaion:

  1. View / View Model Naming Conventions · Caliburn.Micro
    Section: Naming Convention for Multi-View Support
    As mentioned in the Conventions section of the documentation, the framework was designed to handle a one-to-many relationship between ViewModel and View.

  2. Screens, Conductors and Composition · Caliburn.Micro
    Section: Multiple Views over the Same ViewModel
    You may not be aware of this, but Caliburn.Micro can display multiple Views over the same ViewModel. This is supported by setting the View.Context attached property on the View/ViewModel’s injection site.

I hope this helps to clear things up.

2
Won't you need to fully classified name "WpfApplicationExample.MVVM.File.Details"? - Nikita Shrivastava
It is not clear what you are attempting to do with the "View.Context" here. Caliburn takes care of the View-ViewModel Context mappings for you, why are you setting this yourself? - MoonKnight
Updated the question with more detailed explanation. - cryodream

2 Answers

1
votes

The View.Context needs to be placed on the ContentControl where the view is being injected, for the case of a ListView you'd need to modify the ItemTemplate.

<ListView.ItemTemplate>
    <DataTemplate>
        <ContentControl cm:View.Model="{Binding}" cm:View.Context="Details" />
    </DataTemplate>
</ListView.ItemTemplate>
0
votes

Yes view switching... <ContentControl x:Name="SomePropertyName" cm:View.Context="Details" /> Don't believe I have ever seen it on a ListView. Since the idea is you are switching out the view. Normally done with <ContentControl cm:View.Context="{Binding CurrentView}" cm:View.Model="{Binding}" />, where CurrentView is something you switch in your viewmodel in question, folder structure will come into play here. First place it will look is in a subfolder in the ViewModel folder ViewModels -> Main would correspond to MainViewModel.

What you have there won't work since the idea for view switching would have to be a datatemplate in the case above. since you are trying to change the actual lay out of the ListView. View switching is not going to be the best solution in this case.

A lot of times those things are changed in listview with a templateselector