WPF-对话相对源绑定(MVVM)

时间:2016-06-24 19:07:05

标签: c# wpf mvvm data-binding

我有一个WPF对话框,我试图访问所有者的ViewModel中的属性。

我已尝试过以下操作,但它会绑定到对话框的ViewModel:

<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, 
        AncestorType={x:Type Window}}, Path=DataContext.Property}"/>

我也尝试过:

<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, 
        AncestorType={x:Type Window}}, Path=Owner.DataContext.Property}"/>

但它给出了相同的结果。

生成对话框的代码用户是:

        var dialog = new Dialog(DialogViewModel)
        {
            Owner = Window.GetWindow(this)
        };

我在StackOverflow中看到了几个问题,但似乎都没有。

有什么想法吗? 是否可以在对话框中有相对来源?

2 个答案:

答案 0 :(得分:1)

如果我在子窗口中明确设置了所有者,这对我有用:

<ComboBox 
    ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Owner.DataContext.Property}"/>

然而:有一个重要的警告,我认为这可能是您遇到的问题:如果子窗口是父级的私有成员,我在显示子窗口之前设置了所有者,它会在显示子窗口之前尝试解析绑定。当时所有者为空,并且稍后再次设置所有者时不会再次尝试。

但是,如果我在显示它的方法中创建一个新的子窗口实例,请设置Owner,然后在其上调用ShowDialog(),使用Owner的非null值正确解析绑定。我有理由相信这是因为所有者不是DependencyProperty并且也没有引发PropertyChanged,所以没有任何事情会导致任何更新发生以响应所有者更改的值。如果我在UI线程阻塞事件处理程序时将其设置在窗口的新实例上,那么新窗口实例在设置其所有者之后就不会使用绑定做任何事情。但是如果我之前创建它然后让UI线程运行,那么它已经太晚了。

这不是你想搞砸的东西。

我的建议:

为子窗口提供如下属性:

#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

然后当你显示子窗口时......

var dialog = new Dialog(DialogViewModel)
{
    Owner = Window.GetWindow(this),
    OwnerDataContext = DataContext
};

作为DependencyProperty,绑定将正确地与它进行交互。所有者窗口可以随意设置它,您可以绑定它。绑定的方式,它是鸭子类型,所以对OwnerDataContext具有声明类型的Object的绑定完全没有关系。无论如何,这都是反思。

<ComboBox 
    ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=OwnerDataContext.Property}"/>

我可能完全错误地解释了为什么你的代码不起作用,但我敢打赌这在任何情况下都会有用。

答案 1 :(得分:0)

wpf + mvvm + Shell启动了project +多个子模块,当您想在子模块的viewmodel中写一些数据时,可能会调用Sheel作为dll来调用SubModuleA。

要在SubModuleA中将数据写入子模块的资源文件中,例如SubModuleA / Resource / Data / JsonData.json此文件。

在SubModuleA的视图模型中,相对文件路径为

string jsonFilePath =“” ../../../ SubModuleA / Resource / JsonData / JsonData.json“;