0

I have a xaml file with with an entry. I am binding the specific entry to a specific viewmodel. But the viewmodel expects a Navigator. How can I pass the navigator from the xaml file to the viewmodel?

     <Entry  Text="{Binding Signature, Mode=TwoWay}">
        <Entry.BindingContext>
            <vm:SignaturePopupViewModel>
                // I need to pass a navigator..

            </vm:SignaturePopupViewModel>
        </Entry.BindingContext>
    </Entry>

The viewmodel expects a navigation object. I use it to pop the page to go back to the previous page after running some code logic.

    public SignaturePopupViewModel(INavigation navigation = null)
    {
        Navigation = navigation;

        SendSignatureCommand = new Command(async () =>
        {
            await SendSignature();
            await Navigation.PopAsync();
        });
    }
M Yil
  • 877
  • 1
  • 14
  • 35

2 Answers2

2

You do not need to use INavigation navigation in your SignaturePopupViewModel in your constructor to achieve the Navigation.

Just use a simple way is

await Application.Current.MainPage.Navigation.PopModalAsync(); Or

await Application.Current.MainPage.Navigation.PopAsync()

like following code.

   public class SignaturePopupViewModel
{

    public ICommand SendSignatureCommand { protected set; get; }
    public SignaturePopupViewModel( )
    {


        SendSignatureCommand = new Command(async () =>
        {


            await SendSignature();
            // if you use the     MainPage = new NavigationPage( new MainPage()); in 
            //App.xaml.cs use following code.
            await Application.Current.MainPage.Navigation.PopAsync();

             // if not, just use await Application.Current.MainPage.Navigation.PopModalAsync();
        });
    }
}
Leon
  • 8,404
  • 2
  • 9
  • 52
1

Could you create an instance of the SignaturePopupVM in the ViewModel of that page and then bind the Text to that property instead?

VM:

SignaturePopupViewModel SignaturePopupVMInstance { get; private set; }
public ParentVM()//Constructor
{
    SignaturePopupVMInstance = new SignaturePopupViewModel(new Navigator());
}

Xaml:

     <Entry  Text="{Binding SignaturePopupVMInstance.Signature, Mode=TwoWay}"/>

Edit:

public class TabPageVM{
   public ChildVM TheVMForTabOne { get; set; }
   public AnotherChildVM TheVMForTabTwo { get; set; }
   public TabVM TheVMForTabThree { get; set; }

   public TabPageVM(){
      TheVMForTabOne = new ChildVM(/*parameters*/);
      TheVMForTabTwo = new AnotherChildVM(/*parameters*/);
      TheVMForTabThree = new TabVM(/*parameters*/);      
   }

}

Xaml for tabpage:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:Views="clr-namespace:App.ViewsForMyTabs"
             x:Class="App.TabPageView"
             BarBackgroundColor="#EEEEEE"
             BarTextColor="Black"
             BindingContext="{Binding TheTabbedPageVMInstance}">
    <TabbedPage.Children>
        <Views:TheViewForTabOne x:Name="TabOneView"
                                BindingContext="{Binding TheVMForTabOne}"/>
        <Views:TheViewForTabTwo x:Name="TabTwoView"
                                BindingContext="{Binding TheVMforTabTwo}"/>
        <Views:TheViewForTabThree x:Name="TabThreeView"
                                  BindingContext="{Binding TheVMforTabThree}"/>
    </TabbedPage.Children>
</TabbedPage>

Lets say TheViewForTabOne has the button on it that takes you to the new page. The VM for that view "TheVMForTabOne" would have something like this:

public class ChildVM{
   public SignaturePopupViewModel SignaturePopupVMInstance { get; set; }
   public Command NavigateToNewPageWithEntry { get; private set; }

   public ChildVM(){
      SignaturePopupVMInstance = new SignaturePopupViewModel(/*parameters*/);

      NavigateToNewPageWithEntry = new Command(() =>{
          //Navigate to new page with SignaturePopupVMInstance as the BindingContext
      }
   }
}

TheViewForTabOne
...
<Label Text="{Binding SignaturePopupVMInstance.Signature}"/>
<Button Command="{Binding NavigateToNewPageWithEntry}"/>
...
  • But I need to set the bindingcontext of that Entry view right? – M Yil Mar 09 '20 at 15:02
  • The xaml file has multiple binding contexes. That's why I need to set the binding context in the view. How can I set the bindingcontext for the specific entry if I can ask? – M Yil Mar 09 '20 at 15:04
  • Maybe the correct question would be: How can I reference the SignaturePopupVMInstance from the xaml file so that the entry view can set the bindingcontext? (The page has multiple views, some views reference other bindingcontexes, thats why) – M Yil Mar 09 '20 at 15:10
  • if you're following MVVM your Content Page needs to have one BindingContext for the whole page. Then if you need controls inside the page to bind to other ViewModels you can make those other viewmodels properties on the ContentPage's vm; the parent VM, if you will. – Jonathan Cook Mar 09 '20 at 15:12
  • I have the following problem: The app is based on tabbed pages. One of the tabbed pages has a button on it. When I click on it, a new pages opens. On that page I can fill an entry. When I press submit, the page will pop and I go back to the previous page, the tabbed page. On that tabbed page I want to show the text written in the entry. – M Yil Mar 09 '20 at 15:16
  • That's why I wanted to bind a page with the viewmodel, and the other page, I only wanted to bind the view with the viewmodel, so when a change happens, the UI gets updated. And Yes, I am following the mvvm pattern. – M Yil Mar 09 '20 at 15:18
  • You can achieve your goal using xamarin forms messaging center https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/messaging-center – Marcel Callo Mar 09 '20 at 15:32
  • Yes the messaging center should work. I am not sure I am understanding your requirements but I will edit my original post to show you how I would do it. – Jonathan Cook Mar 09 '20 at 16:13