Among client applications, this problem is the most common among Single Page applications. Experienced developers often split a View into several Views as sub-Views. These jobs require a lot of practical knowledge.
A Prototype Chain for JavaScript
When the word “sharing” is first mentioned, the first thing that comes to my mind is “inheritence”. Because you are a child of a parent, so sharing essentially means building an “inheritence chain”, and this is known in JavaScript as a “Prototype Chain”.
So how is this implemented in JavaScript? To ensure this, a built-in attribute is applied “proto”, how to implement the inheritence chain between ViewModels is shown below:
Creating Inheritance Relationship for ViewModel
After the above analysis, when we look at the implementation of “proto” in the JavaScript language, we add a ParentViewModel attribute to the ViewModelBase to represent the parent.
public class ViewModelBase
{
public ViewModelBase ParentViewModel { get; set; }
//...
}
Now let’s see how we access the data in the parent ViewModel in WPF:
Binding = "{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType = {x:Type Window}}, Path=DataContext.ParentViewModelProperty}
When we look at the usage above, a FindAncestor method is used to get data from a parent object according to the object specified with AncestorType. Starting from here, we are preparing an extension method for our ViewModel.
public static IEnumerable<T> Ancestors<T>(this ViewModelBase origin) where T : ViewModelBase
{
if (origin==null)
{
yield break;
}
var parentViewModel = origin.ParentViewModel;
while (parentViewModel!=null)
{
var castedViewModel = parentViewModel as T;
if (castedViewModel != null)
{
yield return castedViewModel;
}
parentViewModel = parentViewModel.ParentViewModel;
}
}
Thanks to this method, we can get the data of the object in the upperclass with the following usage.
var ancestors = this.Ancestors<FaceBoxViewModel>();
Our app has now become more intuitive. According to the inheritance chain, ParentViewModel’s data can be easily accessed with SubViewModel.