
Toolkit and community would benefit tremendously if we had a control that implemented the master detail pattern described here
https://msdn.microsoft.com/en-gb/windows/uwp/controls-and-patterns/master-details
Discussing online with @ScottIsAFool @Depechie @bartlannoeye and Shawn Kendrot and moving it here.
@Depechie all yours
Well I'll share the details how we did it in https://github.com/AppCreativity/Kliva
It's not a control for now though.
We added our own ApplicationFrame, this to handle the SplitView control, because on Side-By-Side view we show the SplitView, in Stacked mode we show bottom appbar. We check this with view width.
Secondly our main page will act like a shell, so has 2 controls on it, the list of data and the details of a selected item in the list, shown side by side.
If we are on a small device, we hide the details control and trigger a page navigation to show the details.
That's it basically
Note that we also use the Connected Animation on smaller devices when we navigate.
Here is another implementation if you need inspiration (does not use SplitView):
https://github.com/Code-ScottLe/USCISTracker
if we are on a small device, we hide the details control and trigger a page navigation to show the details.
on which frame that the detail would be displayed? The custom frame that the control uses or the main frame that the application use?
It would be nice to not have to navigate to another page to view the details if on smaller devices. Instead "fake" a navigation. I have a MasterDetailsPanel that I wrote a year ago. I'll find it and give it some polish.
It is true to not have to navigate to another page. Repeated code and data transitions were a pain.
Hmm by use of user controls and MVVM we have almost 0 code duplication and no faking navigation, you'll have to fake all animation transitions and we all know now those can change when switching WP OS version :P
When i first implemented this , i literally had to copy and pasted the code from the detail section in the Master-Detail page, onto the Detail page, just because I was too dumb to start the implementation using only Grid.
Using Splitview and collapse the panel on mobile for detail section makes much more sense imo.
I'm knocking something up for this at the moment
Well, I have a working control that behaves exactly as expected (albeit with no animations right now), but it doesn't work in the sample app because the sample app has a messed up navigation approach where a control can't prevent a back navigation because it can't access the frame being used.
I have a control with animations. I ha e tested navigation within my own app, but I have not tested it within the sample app. I can test that later today.
@skendrot I suspect whatever mechanism you have in place will also fall over with the sample app.
I think that a simply approach is needed for a control like this. The vast majority of use cases will only need a List for the "master". We would want to make it easy for beginner/intermediate developers to use these controls.
Compare the two examples:
Option A:
<controls:MasterDetailsView ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource ListTemplate}"
DetailsTemplate="{StaticResource DetailsTemplate}"/>
Option B
<controls:MasterDetail x:Name="MasterDetail" DetailsTemplate="{StaticResource DetailsTemplate}">
<controls:MasterDetail.Master>
<ListView x:Name="ItemsList"
SelectionChanged="ItemsList_OnSelectionChanged"
ItemTemplate="{StaticResource ListTemplate}"/>
</controls:MasterDetail.Master
</controls:MasterDetail>
And code behind for Option B:
// Could probably use binding within the definition in xaml
private void ItemsList_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
MasterDetail.Detail = e.AddedItems.FirstOrDefault();
}
Providing an easy to use control that allows for advanced developers to style and add additional features covers all cases.
EDITED (Scott): updated option B to show the current required code as visual states are no longer required to use the control.
I do appreciate the NoSelectionView property of @ScottIsAFool's, but would this be used often? I can't recall of an app that has something like this in it.
Is OptionB actual user code?
I do appreciate the easiness of option A which is clearly aligned with Toolkit philosophy.
It's a condensed version of the sample page provided for Option B
This is definitely one point for OptionA ;D
Why not adding support for NoSelectionView? it seems fairly important to me
At first I was also very happy with the small footprint of option A!
But looking in more detail to my own app where I want to use it, we have a 'filter' list dropdown above the ListView in the Master part. So maybe extend with some HeaderTemplate option?
The plan is to be able to use the control in 99% of the time so a footerTemplate will be required then
I like the idea of a ListHeader and ListHeaderTemplate. @deltakosh can you name any iOS/Android or windows apps that tell the user "No selection" or something similar? I have not seen any, but I also don't use a lot of apps
Mine :) (UrzsaGatherer and Cast). When there is no selection I display a text to give user some feedback or guidance

Filter and empty detail
Well there you have it!

Skype preview does this too and also has search option in Header of Master
And a footer with commandbar
Reason for the visual states is to give the control to the developer over what triggers are used for switching from full to compact mode. The code behind part is not a real world usage in all honesty as that would generally be bound to from your view model.
Question for OptionA: How to define the width of master list
Other thing I would like to see is a method to map from the selected item model to the detail item model.
By default the model sent to the detail view is the main list selected model but you may want to lazy load more info or a totally different object.
For instance if you think about Skype the detail part contains different data (like conversation history) than the summary one on the left.
I keep adding to my wish list :) We need a way to define the Listview like the GridView.ItemContainerStyle or something like that
I still believe this control should cater for non-list usages. I needed this control last week for the app I work on, and one that doesn't support non-list would literally have been useless for us. I think this use case is being dismissed far too readily.
Why not try to merge both initiative by pulling in an option to support non list master template?
Added the following properties to Option A:
MasterHeader and MasterHeaderTemplate
NoSelectionContent and NoSelectionContentTemplate
Added ItemContainerStyle template binding to the ListView. The MasterDetailsView is already an ItemsControl so it already had the ItemContainerStyle property
I would not say a "no list" option is being dismissed. I'm saying a "no list" option is a small minority of use cases. The Master/Details pattern is a pattern that is based on a list of items. From the docs:
The master/details pattern works well if you want to:
- Build an email app, address book, or any app that is based on a list-details layout
- Locate and prioritize a large collection of content.
- Allow the quick addition and removal of items from a list while working back-and-forth between contexts..
A control that implements the pattern should be based on a list of items. Styling the control to remove the ListView is easy enough for the small minority that would need to do that
Solved the issue of the sample app not allowing the sample page to handle the back button: https://github.com/Microsoft/UWPCommunityToolkit/pull/483/commits/96968e5e42f5a0518212e61495bc3e6be4294970
If you keep adding List/GridView type properties to yours @skendrot, would it not make more sense for your control to just inherit from ListView?
I don't believe any ListView/GridView properties were added. The MasterHeader property is stationary unlike a ListView header. The MasterDetailsView is an ItemsControl, so it already has properties like ItemTemplate, ItemsSource, etc. I would prefer that the control inherits from Selector but it has an internal constructor for some reason.
Ah, was thinking you'd done the changes suggested by @deltakosh about doing things like ItemContainerStyle, etc.
Yea, it already has those properties. I just added the template binding of the ListView to those properties
Could you add this one as well:
Other thing I would like to see is a method to map from the selected item model to the detail item model.
By default the model sent to the detail view is the main list selected model but you may want to lazy load more info or a totally different object.For instance if you think about Skype the detail part contains different data (like conversation history) than the summary one on the left.
@deltakosh is that really needed? The dev either listens to the selectionchanged event, or has some code in their viewmodel to know when the selecteditem changes and calls a lazy load method from there. I don't think that's something the control needs to do.
What exactly would that entail? Couldn't the Skype example be handled by a Contact object with a Conversation property that supports ISupportIncrementalLoading to load the conversation
This is more for beginner developers or "old school" ones who want to be able to trigger the lazy loading at that time without having to catch the item click and do the change manually.
It is an easy to develop feature that can help guiding new comers (the real world is full of developers not following the MVVM pattern :))
And yes I know that there are other way to do it :)
Something like MyMasterDetail.Map = (main) => detail;
by default this delegate is null and return the main object.
Doesn't that complicate things a bit? My idea with this control is it's a Selector (although it cannot inherit from Selector). It has a SelectedItem property, fires the SelectionChanged event etc. It's very similar to a ComboBox. There's a selected item that has a different display from the list of items.
It allows for more control I would say.
You can still fire the SelectionChanged and provide two values: master model and detail model. By default they are the same. But you allow the user to provide a map function to change the detail model.
By complicates things I mean you no longer have the SelectedItem property being what drives the details view or that property cannot drive the selection on the listview. Would need an additional DetailsItem property or something similar and then how does this work with two way binding to the SelectedItem? Or twoway binding to the DetailsItem property? How do you drive the selection of the ListView when you set the SelectedItem property to be some more complex object, or set the DetailsItem property within your viewmodel/code-behind?
I will not change the way it works now.
Only change will be that instead of binding the SelectedItem, I will bind the Map(SelectedItem) (where Map == identity by default)
I'll admit, I like having the option to provide a maping function instead of having to implement lazy loading on my data model. A lot of service apis have different models for overview and details of the same data, and this could make it easier to request data on demand.
Most of the time, I'm a passive observer on this project, thought I'd chime in here..
I like the simplicity of the ListView implementation, but honestly in the real world, isn't there a lot of cases where the selection could be made from any sort of control, not necessarily a list? It could come from search fields, other UI interactions such as buttons, selections or something 3rd..
I know the most general case most likely will be a list, but I would see it as a clear limitation with I was forced to use something because of the control. I fully understand the ListView makes everything easier and simpler, but it would introduce a clear limitation which could keep people from using the control in a lot of scenarios.
@nmetulev that would only be the case if the control was based on a list though, right? If you were to use my implementation (where you can add what you like to the master), that's not so applicable is it? As the selection changing isn't hidden from the consuming dev.
Yep this won't be required. I would be happy to vote to option B if you can streamline it a bit 脿 reduce the work required on developers side
@deltakosh the only thing I can do is create another control that uses my MasterDetail that is purely ListView based, although to be perfectly honest, I really don't see how my implementation is "difficult" and why it needs to be cut down any more than what it is right now. When you compare https://github.com/Microsoft/UWPCommunityToolkit/issues/452#issuecomment-254340439
Oh you removed all the VSM? This is completely different then!
Would love to get other voice here as I hate cutting a PR (And we need to cut one...)
@deltakosh I removed that ages ago, and told you I had ;) btw, the snap points are still customisable as they were before, you just don't need the visual states.
I know..I'm underlining it for the community!
I don't want to choose alone.This is not how the toolkit should work. It should be a decision coming from the majority of contributors/developers.
My vote goes to your PR because of flexibility and because it became simple enough to reach our min bar
Not tested code yet, but in our Kliva app we switch the splitview over to phone page bottombar on master and detail. Would this still be possible? I would think yes but with some plumbing?
@Depechie sorry, I don't follow, do you mean you hide the splitview pane, and show a bottom appbar?
Yeah and a different one on master and detail
You could bind to the Masterdetail.VisibleDisplay property to change appears.
I'm certain that if Microsoft were developing a MasterDetailsView control that it would inherit from Selector, or possibly ListViewBase. The Master pane would have a default implementation. Would that implementation be a ListView exactly? Probably not, but it would behave much like a ListView.
In software development you optimize for the 80% use case. In this situation, the 80% use case (probably actually much higher) is to display a list of items. For the rest there is styling. I'm not sure when styling a control became some difficult, advanced concept. It is one if the number one benefits of XAML. Restyling is the flexibility that is given to XAML developers to solve the 5-20% use cases.
Unfortunately, I do not believe that it is possible to add a default view to the master section and allow it to be customized _without_ styling. Adding either a MasterTemplate or MasterControl property to the MasterDetailsView and having a default implementation makes it impossible to properly bind the ItemsSource, ItemTemplate, etc to the control itself without ancestor RelativeSource binding. Using TemplatedParent brings it to the ContentPresenter being used to display such a property.
As it seems the consensus is to require the 80-90% use case to add their own master view. I will close my PR.
Ok, so here's a question that @Depechie may be able to help answer: what is the story on iOS? As they have a MasterDetail control built into the SDK.
Don't close yet. We need more voices to weight in here
Just a control with 2 placeholders for content https://developer.xamarin.com/guides/xamarin-forms/user-interface/navigation/master-detail-page/ but this tends to be more like the split view control! So the actual use case would be menu like system and not true master detail I guess
@Depechie is that the same for xamarin.ios too?
I think we need to get on the same page of what "Master-Detail" means and the mentality of the developers when they decide to do such a thing. I saw a lot of opinions on the case of allowing more freedom on what Master could be (not just ListView). By the end of the day, Master-Detail is not a control, it is a technique/pattern, even the official guide said this:
The master/details pattern works well if you want to:
Build an email app, address book, or any app that is based on a list-details layout.
https://msdn.microsoft.com/en-us/windows/uwp/controls-and-patterns/master-details
Also, this toolkit already has GridSplitter and the Framework already has SplitView, which both allow an extreme degree of freedom for displaying 2 contents at the same time that are related to each other.
Agree with @Code-ScottLe and my vote is still for @skendrot's control. It doesn't cover all use cases but it makes it easier for the majority of cases.
@ScottIsAFool's control is great for giving more flexibility to the dev, but not enough as using a combination of the existing controls in the toolkit/framework would provide (It might as well be just a _Detail_ control).
@code-scottle so your vote is for option A correct?
@deltakosh To be honest, the option A leaves a lot to be desired, but if i have to choose, it will have to be that one. It is clean, it is simple, straight to the point and align nicely with the official guideline - something that dev would expect after reading off what master-detail is.
From that point on, if they need something more advance, using SplitView to do their own thing would be reasonable imo.
Sounds like we have a majority here for option A (for now)
Just a thought: What if the outer part of the master detail part was a Frame: The internals would just navigate to a page that shows the details with the details template, but that also allows the user to navigate within the frame to another page, or navigate to a custom view using myDetailsView.NavigateTo(someOtherPage) ? We also get the benefit of a backstack inside the master details view.
I had thought about making the details panel a frame but decided against for two reasons
Frame navigation is messy.. From what I have seen frequent navigation leads to memory and handle allocations that don't get freed up fast enough.
From the choice, If I was consuming the app, I would prefer the simpler version. Specify ItemSource, Master Item and Detail templates and bingo.
No messing about in the code. No handling selection events etc.
However. We should be able to also set Items directly not just through ItemsSource
Ok so we are heading to:
Sounds reasonable to all? (democracy FTW)
OK. so the last item would be to allow for the following:
public MainPage()
{
InitializeComponenet();
MyMasterView.MapDetailAsync = GetComplexModel;
}
private Task<object> GetComplexModelAsync(object obj)
{
var model = obj as Model;
if(model == null) return;
return Task.FromResult(new ComplexModel(model));
}
And that's better than the following:
// assumes binding of SelectedItem from XAML
public Model SelectedItem
{
get { return _model; }
set
{
_model = value;
if(_model != null)
{
_model.ExtraData = GetExtraData();
}
}
}
Would this be something to add as it's own issue? Do more people want to weigh in? I've seen four people talk about it and it looks split 2-2 on implementing it. I'm ok making the change and I have something that works. Just want to make sure that's the consensus.
Like it. Go ahead please using this PR
Thoughts on the mapping function being async? I'm leaning toward synchronous and letting to user do async work themselves. This allows the details panel to have content that the user can show (loading text) while they are getting the extra info. Making it Async would cause the detail area to be blank unless the user restyled it to show. One possibility for async is to add a loading template that is displayed when getting the mapped data.
Keep things simple:) synchronous is fine
Most helpful comment
Filter and empty detail