Windows-XAML / Template10

Making Windows 10 apps great again
Apache License 2.0
1.41k stars 388 forks source link

Template10 ViewModels can't be Portable #684

Closed nicolgit closed 7 years ago

nicolgit commented 8 years ago

interface INavigable doesn't allow to have the viewmodel classes portables (i.e. common between Win Ios and Android). This makes very complex also the integration with MVVMCross.

Are you planning to fix this in the future?

mvermef commented 8 years ago

Considering this is strictly for windows 10, don't think it will be fixed ever.. Don't think Jerry's intentions for this template were ever to be cross platform in any way.

JerryNixon commented 8 years ago

However, perhaps INav could be altered to help. Tell me the problem, pls.

MichaelPetrinolis commented 8 years ago

Hi, I have done the same and I use shared project for the viewmodels. You need to provide an implementation for the used interfaces. I use xamarinforms and mvvmlight.

domedellolio commented 8 years ago

Same here @JerryNixon ! Below some considerations.

@MichaelPetrinolis could you share an example?

In Template10 v1.0 we were able to achieve all considerations I just explained

nicolgit commented 8 years ago

INavigationService uses:

INavigable uses:

all these classes are UWP specific, so if you want to put a viewmodel class in a PCL cross platform library, you cant.

MichaelPetrinolis commented 8 years ago

@domedellolio I can't share an example, but i can describe what i have done.

I created my own MVVM abstractions, a BaseViewModel (inherited from MVVMLight VM) and defined INavigable,INavigationService,NavigatingEventArgs and NavigationMode in the shared library

On a Xamarin portable project i implemented or extended partially the classes/interfaces that are defined in the shared project.

I did the same for UWP, integrating template 10 in the UWP project.

@JerryNixon now that Xamarin is part of MS, Template10 could be more cross platform friendly ;)

stfnilsson commented 8 years ago

Nice template for win10. I develop my own cross platform "template" with help of Mvvm Light. Now I want to change it to ReactiveUI. Any thoughts of add some reactive pattern to your template?

JerryNixon commented 8 years ago

When the time comes, guys, I will get all of your input on restructuring for Xamarin.

ProH4Ck commented 8 years ago

Here is my situation: Xamarin app with PCL library and MVVM Light. Android and iOS works fine with MVVM Light integrated NavigationService. For the UWP project i created the following "bridge" class to adapt Template10's Navigation Service to the shared one. It works pretty well.

public class MyNavigationService : GalaSoft.MvvmLight.Views.INavigationService
{
    private Template10.Services.NavigationService.INavigationService navigationService;

    public MyNavigationService(Template10.Services.NavigationService.INavigationService navigationService)
    {
        this.navigationService = navigationService;
    }

    public string CurrentPageKey => navigationService.CurrentPageType.Name;

    public void GoBack()
    {
        if(navigationService.CanGoBack)
            navigationService.GoBack();
    }

    public void NavigateTo(string pageKey)
    {
        navigationService.Navigate(Type.GetType(pageKey));
    }

    public void NavigateTo(string pageKey, object parameter)
    {
        navigationService.Navigate(Type.GetType(pageKey), parameter);
    }
}

and in App.xaml.cs

var nav = new MyNavigationService(NavigationService);
SimpleIoc.Default.Register<INavigationService>(() => nav);
selaromdotnet commented 8 years ago

whoa @ProH4Ck you read my mind I ended up doing almost exactly the same thing!

but how are you handling the ViewModels with regard to activating (Onnavigatedto for example)? This requires that your viewmodels inherit INavigable, which is not possible if they exist in the PCL library...

My current attempt to fix this is inheriting the pcl viewmodels in my win10 project, adding inavigable and passing the navigation method and parameters up to the base class, are you doing something similar?

so +1 from me that portable INavigable would really be great!

JerryNixon commented 8 years ago

This will be a goal for 10.2

selaromdotnet commented 8 years ago

That's great to hear jerry, please tell me if and how I can help!

ProH4Ck commented 8 years ago

@selaromdotnet solved also this problem creating a BasePage and let every page in my UWP project inherit from it:

public class BasePage : Page
{
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        var navigableViewModel = DataContext as INavigable;
        if (e.Parameter != null)
        {
            navigableViewModel?.Activate(SerializationService.Json.Deserialize(e.Parameter.ToString()));
        }
        else
        {
            navigableViewModel?.Activate(null);
        }

    }

    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
        base.OnNavigatingFrom(e);

        var navigableViewModel = DataContext as INavigable;
        navigableViewModel?.Deactivate(e.Parameter);
    }
}

MainPage.xaml

<helpers:BasePage x:Class="MyCompany.MyProject.Win10.Views.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:controls="using:Template10.Controls"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
      xmlns:core="using:Microsoft.Xaml.Interactions.Core"
      xmlns:helpers="using:MyCompany.MyProject.Win10.Helpers"
      xmlns:model="using:MyCompany.MyProject.Model"
      mc:Ignorable="d">

    <Page.DataContext>
        <Binding Path="Main" Source="{StaticResource Locator}" />
    </Page.DataContext>

    ...

</helpers:BasePage>

INavigable interface (in PCL project):

public interface INavigable
{
    void Activate(object parameter);
    void Deactivate(object parameter);
}

And then ViewModel (in PCL project too):

public class MainViewModel : ViewModelBase, INavigable
{
    ...

    public void Activate(object parameter)
    {
        ...
    }

    public void Deactivate(object parameter)
    {
        ...
    }
}

I think that actually this is the cleaner solution to achieve this. Now tha UWP app is in production and works perfectly :smile:

akshay2000 commented 8 years ago

@ProH4Ck In this case, the ViewModel cannot handle suspension, can it? I went as far as implementing INavigable interface on my portable ViewModels as you suggested. However, there are two major issues here.

  1. No access to NavigationMode and state in Activate().
  2. No access to isSuspending and state in Deactivate().

How are you getting around this?

angusbreno commented 8 years ago

Hey guys,

Back in time I wanted to work with the same concepts about navigation load and everything for Xamarin Forms so I took T10 as idea base and create this https://github.com/NaylahProject/Naylah

Like I said to Jerry one time, I'm interested in participate bring all it together...

JerryNixon commented 8 years ago

1.1.12 will be the last NuGet package before we rework Template 10. We need a place to propose changes to Template 10 that is more visual than Issues. Any ideas?

callummoffat commented 8 years ago

I'm not 100% sure. Issues is the Github-based method of doing so, and I'm not sure about any others. However, I agree that there needs to be a more visual way of proposing changes.

JerryNixon commented 8 years ago

I've been lamenting that we didn't create a namespace called App, like Template10.App.BootStrapper. Let's pretend that exists. It is where all the navigation logic should go - not in Common. That doesn't make any sense. (a little glimpse into my OCD). I could see several NuGet libraries.

Of course we already have:

But introduce this:

I don't know. I am just starting to think about it seriously. I am also planning on including the UWP Community Toolkit as a built-in part of the templates, even Blank. With that I plan to move a few of the controls (like Resizer) out of T10 and into the Toolkit.

I am also wondering if every control should be its own package.

callummoffat commented 8 years ago

Awesome idea. However, I think the Validation needs to be a PCL, so it is compatible across platforms.

I do think that layout makes more sense. It would also make it easier to branch out, and add new stuff. Could you create a branch where people could start working on these changes?

callummoffat commented 8 years ago

Could we create a new thread in Issues for this? The problem you're lamenting seems to encompass more than just this issue.

ProH4Ck commented 8 years ago

@JerryNixon Packages fragmentation you proposed is correct. If you open a new branch I can help.

JerryNixon commented 8 years ago

When we are done, I think we should be looking at around 12 different libraries. This will allow developers to have significantly smaller payload footprints from Template 10 and allow them to prune out things that don't belong in their particular app. The templates might default to include all, allowing knowledgeable developers to remove what they want and new developers to have a comprehensive experience.

I will have a 2.0.0 branch after I finish with 1.1.12.

callummoffat commented 8 years ago

On the concept of separate packages for each control, maybe there could be a meta-package that allows all these controls to be installed?

JerryNixon commented 7 years ago

They are now