3

I have a Xamarin Forms application with a Master Detail Page as the root view. I am implementing MVVM pattern.

My Root Page loads a Detail Page which is wrapped in a navigation page and a Master Page which is used to display a Menu with links to detail pages.

The Master Page Holds the navigation menu using a List View The Detail Page Holds all the selected items from the Master Page, which will display a new content page.

I would like my detail page to use its own ContentPage Content Property to display the selected page links from the MasterPage. I would like to know if this is possible and if not what are some alternatives.

Here is my ViewModel for the MasterDetailPage.

    public class PageViewModel: ViewModelBase 
    {
    public event EventHandler<string> ItemSelectedEventHandler;
    string _selectedpagelink;
    public string SelectedPageLink
    {
        get { return _selectedpagelink; }
        set
        {
            if (_selectedpagelink != value)
            {
                _selectedpagelink = value;
                OnItemSelected(this,value);
                OnPropertyChanged();
            }
        }
    }




    public ObservableCollection<string> Links => 
    new   ObservableCollection<string>
    {
        "PageOne",
        "PageTwo"
    };

    public PageViewModel()
    {
        this.SelectedPageLink = this.Links.FirstOrDefault();
    }

    protected virtual void OnItemSelected(object sender , string newPage)
    {
        ItemSelectedEventHandler?.Invoke(this, newPage);
    }


}

Here is my converter, which converts the page value into a string, this way it can be navigated to using Resource dictionary.

    public object Convert(object value, Type targetType, object  parameter, CultureInfo culture)
    {
        var key = value as string;
        if (key == null)
        {
            throw new ArgumentNullException("Resource key is not found", nameof(value));
        }

        return Application.Current.Resources[key];
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

here is my Master Page using Content Page and a listView

 **<ListView 
              x:Name="ListViewMenuMaster"
              ItemsSource="{Binding Links}"
              SelectedItem="{Binding SelectedPageLink}"

              SeparatorVisibility="None"
              HasUnevenRows="true">

            <ListView.Header>
                <Grid BackgroundColor="#03A9F4">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="10"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="10"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition Height="80"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="10"/>
                    </Grid.RowDefinitions>
                    <Label
              Grid.Column="1"
              Grid.Row="2"
              Text="My App Name here"
              Style="{DynamicResource SubtitleStyle}"/>

                </Grid>
            </ListView.Header>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Padding="15,10" HorizontalOptions="FillAndExpand">
                            <Label VerticalOptions="FillAndExpand" 
                    VerticalTextAlignment="Center" 
                    Text="{Binding}"

                    FontSize="24"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>**

Here is my Detail Page, which should display the selected link from the Master page

 **<ContentPage.BindingContext>
        <vm:PageViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Resources>
        <ResourceDictionary>
            <conv:ResourceLookUpConverter x:Key="resourceLookupConverter"/>
        </ResourceDictionary>
    </ContentPage.Resources>

     *Can the content property below be used to display the selected page links???*
    <ContentPage Content="{Binding SelectedPageLink, Converter={Binding resourceLookupConverter}}" />**

The Content Pages I am navigating to are of type Content Page that are very simple. I would like to do this without the ViewModel knowing anything about the view. The Implementation I have looks feasible to me at least.. The concern I have is can the Content Page Content property display the selected Master Page links?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Ahhzeee
  • 123
  • 1
  • 12

1 Answers1

3

I don't know if I have understand correctly what you need. If you want to open the ContentPage (Detail) when SelectedPageLink is selected, I think you can use MessagingCenter (Hope it follows MVVM conventions...)

Take a look to this repo

There is a MasterPage where, in the code behind, there is this code

    protected override void OnAppearing()
    {
        MessagingCenter.Subscribe<MasterPageViewModel, string>(this, "Detail", (arg1, arg2) => {

            ((MasterDetailPage)Application.Current.MainPage).Detail = new DetailPage(arg2);
            ((MasterDetailPage)Application.Current.MainPage).IsPresented = false;
        });
        base.OnAppearing();
    }

    protected override void OnDisappearing()
    {
        MessagingCenter.Unsubscribe<MasterPageViewModel, string>(this, "Detail");
        base.OnDisappearing();
    }

it receives a Message from its ViewModel when an Item is selected in the list

    public MyModel SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (_selectedItem != null)
                _selectedItem.Selected = false;

            _selectedItem = value;

            if (_selectedItem != null)
            {
                _selectedItem.Selected = true;
                MessagingCenter.Send<MasterPageViewModel, string>(this, "Detail", _selectedItem.Name);
            }
        }
    }

in arg2 there is the Name selected in the list. a DetailPage is created with this Name (it is passed to DetailPageViewMode and is bind to a Label in Detail page)

Hope it helps

Alessandro Caliaro
  • 5,623
  • 7
  • 27
  • 52
  • Thank you for the suggestion unfortunately this does break the MVVM pattern, because we are writing view logic in the view. What I am trying to do is display a new content page in the Detail Page which is of type content page. Every time a link is selected from the Master Page Menu it needs to load the desired Page View. – Ahhzeee Mar 21 '17 at 22:19
  • 2
    Are you sure it breaks the MVVM pattern? MVVM send only a Message that someone receive. I think MessagingCenter substitute other things that MVVM frameworks does http://stackoverflow.com/a/3388241/4399386 – Alessandro Caliaro Mar 22 '17 at 08:45