Reputation: 3115
I have a WPF Dialog, and I'm trying to access a property in the ViewModel of the Owner.
I've tried the following but it binds to the ViewModel of the dialog:
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=DataContext.Property}"/>
I also tried:
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=Owner.DataContext.Property}"/>
But it gives the same result.
The code user to generate the dialog is:
var dialog = new Dialog(DialogViewModel)
{
Owner = Window.GetWindow(this)
};
I've seen several questions in StackOverflow but none seems to work.
Any ideas? And is it possible to have a relative source in a dialog?
Upvotes: 1
Views: 577
Reputation: 1
wpf+mvvm+Shell started project+multiple submodules,when you want to write some data in viewmodel of submodule which maybe called SubModuleA,will be invoked by sheel as dll.
In SubModuleA when you want to write data into resource file of submodule such as SubModuleA/Resource/Data/JsonData.json this file.
In viewmodel of SubModuleA,the relative file path is
string jsonFilePath= "../../../SubModuleA/Resource/JsonData/JsonData.json";
Upvotes: 0
Reputation: 37059
This is working for me if I explicitly set Owner on the subwindow:
<ComboBox
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Owner.DataContext.Property}"/>
However: There's an important caveat, which I think might possibly be the issue you're having: If the subwindow is a private member of the parent and I set the owner just before showing subwindow, it tries to resolve the binding before the subwindow is displayed. Owner is null at that time, and it doesn't try again when Owner is set again later on.
However, if I create a new instance of subwindow in the method where I show it, set Owner, then call ShowDialog() on it, the binding is correctly resolved with the non-null value for Owner. I'm reasonably confident the reason for this is that Owner isn't a DependencyProperty and also doesn't raise PropertyChanged, so there's nothing happening to cause any updates to happen in response to the value of Owner changing. If I set it on a new instance of a window while the UI thread is blocking on an event handler, then the new window instance doesn't get around to doing anything with bindings until well after its Owner is set. But if I created it earlier and then let the UI thread run, then it's already too late.
This is not something you want to mess with.
My recommendation:
Give your subwindow a property like so:
#region OwnerDataContext Property
public Object OwnerDataContext
{
get { return (Object)GetValue(OwnerDataContextProperty); }
set { SetValue(OwnerDataContextProperty, value); }
}
public static readonly DependencyProperty OwnerDataContextProperty =
DependencyProperty.Register("OwnerDataContext", typeof(Object), typeof(SubWindow),
new PropertyMetadata(null));
#endregion OwnerDataContext Property
Then when you show the subwindow...
var dialog = new Dialog(DialogViewModel)
{
Owner = Window.GetWindow(this),
OwnerDataContext = DataContext
};
Being a DependencyProperty, bindings will interact with it correctly. The owner window can set it at will and you can bind to it. The way binding works, it's duck-typed, so it doesn't matter at all to a binding that OwnerDataContext
has a declared type of Object. It's all reflection anyhow.
<ComboBox
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=OwnerDataContext.Property}"/>
I may be totally wrong about why your code isn't working, but I bet this will work in any case.
Upvotes: 1