Reputation: 5444
MainWindow is bound to MainViewModel
and the rest are all bound to ChildViewModel
which is a property of MainViewModel
. Now in the innermost child window, which is bound to ChildViewModel
, I want to bind a property to MainViewModel
.
I'm using the following code:
Here the first value of the Converter
is bound to property C
in ChildViewModel
and it works. I have tried to bind the second value to a property to the DataContext of MainWindow
(MainViewModel
) with no success.
<MultiBinding Converter="{StaticResource UnitConverter}">
<Binding Path="C"/>
<Binding RelativeSource="{RelativeSource FindAncestor,
AncestorType={x:Type Window}, AncestorLevel=2}"
Path="DataContext.CurrentTargetUnit"/>
</MultiBinding>
--- Main Window -------------------------------------------
- ----- User Control 1 ------------------------------- -
- - ---- User Control 2-------------------------- - -
- - - ------ Child Window 1 ---------------- - - -
- - - - ----- Child Window 2 ---------- - - - -
- - - - - - - - - -
- - - - - [Bind to MainViewModel] - - - - -
- - - - - - - - - -
- - - - ------------------------------- - - - -
- - - -------------------------------------- - - -
- - --------------------------------------------- - -
- ---------------------------------------------------- -
-----------------------------------------------------------
Update:
My best guess is that one only can bind to the parent window and not higher than that. Maybe the uppermost window is not in the visual tree?
Upvotes: 1
Views: 989
Reputation: 31616
Create a property on the ChildViewModel
which is a referential link to the MainViewModel
. Upon the instantiation of the child VM, link it to the MainViewModel
. Then the internal windows/controls can get to the MainViewModel
by referencing the aformentioned ChildViewModel
property to the main vm.
On the User Control1 and 2 create a dependency property of the main view model's type such as:
// <summary>
/// Holds the parent VM here.
/// </summary>
public MainVM ParentVM
{
get { return GetValue(ParentVMProperty) as MainVM; }
set { SetValue(ParentVMProperty, value); }
}
/// <summary>
/// Identifies the ParentVM dependency property.
/// </summary>
public static readonly System.Windows.DependencyProperty ParentVMProperty =
System.Windows.DependencyProperty.Register(
"ParentVM",
typeof(MainVM),
typeof({Insert Control1 or 2 class type here}),
new System.Windows.PropertyMetadata(null, OnParentVMPropertyChanged));
/// <summary>
/// ParentVMProperty property changed handler.
/// </summary>
/// <param name="d">BeginRandom that changed its ParentVM.</param>
/// <param name="e">Event arguments.</param>
private static void OnParentVMPropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
{
var source = d as {Insert Control1 or 2 class type here};
MainVM value = e.NewValue as MainVM;
}
Since each window will have a reference available to the MainWindowVM, all you have to do is path to the current window's ParentVM
property.
Note that to create control's dependency properties I use the handy snippets, written for Silverlight, but all of them work in WPF:
Helpful Silverlight Snippets - Jeff Wilcox
Upvotes: 1