locked
MVVM with Master Detail Pages RRS feed

  • Question

  • User192776 posted

    Hello, In a windows native application I was able to use DataTemplates and MVVM to switch between content pages. I have been scouring for a similar solution for Xamarin.Forms to have the NavPage of the Master Detail behave similarly but have been unsuccessful in figuring this out. Any assistance is greatly appreciated.

    From my WPF native windows application:

    View:

        <Window ...>
         <Window.Resources>
            <ResourceDictionary>
                <DataTemplate DataType="{x:type viewmodel:MonthlyViewModel}">
                     <view:MonthlyControl/>
                </DataTemplate>
                <DataTemplate DataType="{x:type viewmodel:WeeklyViewModel}">
                     <view:WeeklyControl/>
                </DataTemplate>
            </ResourceDictionary>
        </Window.Resources>
        <StackPanel>
            <Border>
                <ContentControl Content="{Binding SelectedSchedule}" />
            </Border>
            ...
        </StackPanel>
        ...
      </Window>
    

    ViewModel:

            public class MyWindowViewModel {
                    IScheduleStrategy currentSchedule;
    
                    public MyWindowViewModel() {
                            CurrentSchedule = new MonthlyViewModel();
                    }
    
                    public ListItemViewModel<IScheduleStrategy> CurrentSchedule { 
                        get { return currentSchedule; }
                        set { SetProperty(ref currentSchedule, value); }
                   }
            }
    
    Wednesday, April 6, 2016 6:52 PM

Answers

  • User192776 posted

    I was able to accomplish the basics of getting the MasterDetailPage to follow the MVVM pattern. I have outlined the change here.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, April 26, 2016 1:49 PM

All replies

  • User37696 posted

    @HuntJason,

    You may want to take a look at ControlTemplates. Jason posted about this on his blog, here.

    There is also another great post here.

    Another technique I have used is to make my own custom view that can swap it's content out based on a DataTemplate, using a DataTemplateSelector. Something like this:

    ``` // TemplatedGrid.xaml

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    
    <Grid x:Name="ContentGrid" Grid.Row="0" />
    

    ```

    ``` // TemplatedGrid.xaml.cs public partial class TemplatedGrid : Grid { public TemplatedGrid() { InitializeComponent(); }

        public static readonly BindableProperty ContentTemplateSelectorProperty =
            BindableProperty.Create(nameof(ContentTemplateSelector), typeof(Utility.DataTemplateSelector), typeof(TemplatedGrid), default(Utility.DataTemplateSelector));
    
        public DataTemplateSelector ContentTemplateSelector
        {
            get { return (Utility.DataTemplateSelector)GetValue(ContentTemplateSelectorProperty); }
            set { SetValue(ContentTemplateSelectorProperty, value); }
        }
    
        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();
    
            if(BindingContext != null)
                SetContent();
        }
    
        void SetContent()
        {
            ContentGrid.Children.Clear();
    
            var template = ContentTemplateSelector.SelectTemplate(BindingContext, this);
            var view = template.CreateContent() as View;
            view.BindingContext = BindingContext;
    
            ContentGrid.Children.Add(view);
        }
    }
    

    ```

    Then, you can use it like this:

    // "controls" is just my xmlns definition for the namespace of this custom control <controls:TemplatedGrid BindingContext="{Binding SomeContext}" ContentTemplateSelector="{StaticResource TemplateSelector}"/>

    // Resources <util:CustomTemplateSelector x:Key="TemplateSelector"/>

    util:CustomTemplateSelector is an instance of DataTemplateSelector, exampled here.

    Thursday, April 7, 2016 3:39 PM
  • User192776 posted

    After reading more about the Hamburger Menu pattern and why to avoid it, I changed from wanting to use the MasterDetailPage and switched to the TabbedPage as my main form of navigation within my application. I was also able to accomplish the desired MVVM pattern by modifying the TabbedPage thanks to help from the BindablePicker example here in the forums.

    Wednesday, April 20, 2016 1:32 PM
  • User120969 posted

    In my app I use Messaging Center to request a change of the detail. It's the easier clean way I found.

    Wednesday, April 20, 2016 7:13 PM
  • User192776 posted

    One problem with using the Messaging Center is that, because it's a singleton, it's not as easily testable.

    Wednesday, April 20, 2016 7:40 PM
  • User120969 posted

    Messaging Center does have it's downsides, especially if you forget to Unsubscribe ;). It's still a great feature with a lot of flexibility that I'm not sure many people are aware of it's existence.

    Wednesday, April 20, 2016 8:03 PM
  • User192776 posted

    It is great, but I suspect that utilizing it as a mechanism to change/add details is somewhat of a golden hammer.

    Wednesday, April 20, 2016 8:16 PM
  • User192776 posted

    I was able to accomplish the basics of getting the MasterDetailPage to follow the MVVM pattern. I have outlined the change here.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, April 26, 2016 1:49 PM
  • User172554 posted

    @JohnMiller : could you please post a link to the complete solution for swapping the content of the custom view, using a DataTemplateSelector ?

    Monday, July 17, 2017 3:55 PM