【问题标题】:WPF Binding to a property of another windowWPF绑定到另一个窗口的属性
【发布时间】:2018-07-09 14:13:37
【问题描述】:

我有以下配置:

MainWindow.xaml

<Window x:Class="MYNS.MainWindow"
        mc:Ignorable="d"
        x:Name="mainWindow"
        ...

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public Options Options { get; private set; }

    public MainWindow()
    {
        Options = new Options();
    }
}

Options.xaml

class Options 
{
    public bool QuietMode { get; set; }

    public Options()
    {
        QuietMode = true;
    }
}

现在我想将此布尔值绑定到另一个窗口的CheckBox 控件,所以我有

OptionsWindows.xaml

<CheckBox 
  Content="Quiet Mode" 
  DataContext="{Binding ElementName=mainWindow, Path=Options}"
  IsChecked="{Binding Path=QuietMode}"
/>

虽然我会做到这一点,但它不起作用(我尝试了多种类似的方法,但到目前为止都没有奏效)。由于我对 WPF 很陌生,我想我显然在这里遗漏了一些东西。

【问题讨论】:

  • 两个窗口可以共享同一个DataContext。
  • 很明显Options属性是一个“模型”属性,需要在视图模型中,而不是在视图类中。
  • @dymanoid:实际上,到目前为止,我不需要将 Options 对象直接绑定到 OptionsView 中的任何东西(尽管从另一个视图设置,但这些 Options 已在 MainWindow 代码中使用),所以没有到目前为止还不是问题
  • “到目前为止”表示您现在需要它。这就是为什么你应该按照之前的 cmets 的建议,将这些数据重构到一个共同的地方(一个共同的 Model 或 ViewModel,它将是两个 View 的 DataContext)。
  • @heltonbiker:我明白你在说什么,但不清楚这个 Options 的实际实例(或包含它的 DataModel)将在哪里声明和保存。我想在某处明确分配逻辑对象(如Options),如果不是静态实例,我看不出谁将拥有Options

标签: c# wpf xaml data-binding


【解决方案1】:

ElementName 的绑定只能在同一个用户控件内工作。如果两个 Windows 完全分离,除了将 Options 属性从 MainWindow 类移动到适当的 Model 或 ViewModel 类之外,您别无选择,无论如何您都应该这样做,因为 WPF/MVVM 应该是这样的。

如果你真的想从一个视图绑定到另一个视图,不同的 Window 实例至少应该共享一些共同的祖先,这样你就可以使用ElementName,而不是ElementName @Binding 参数,但我怀疑这将是一个简单的、自然的、甚至可能的解决方案。 (我认为这甚至是不可能的,因为 Window 是一个“顶级控件”,它在 Logical or Visual Trees 中没有父级。

到目前为止,最好的解决方案是尽快将模型数据从视图中移走,这样您将获得一个更容易工作的环境来进行改进。


更新:一些 MVVM 上下文:

通常在 WPF 应用程序中,您有一些与“视图”层(Windows、控件、复选框)相关的类和其他与“[View]Model”层相关的类,您可以在其中放置选项类。您需要以一种方式引导您的应用程序,在启动执行过程中,您很快就会拥有一个 View 实例和一个 ViewModel 实例,而后者应该设置为前者的 DataContext,这样您就可以使用数据绑定。

围绕"View-First" vs "Model-First" approach 存在一些宗教战争,但我也不使用任何一种:我总是有一个BootStrapper 类来创建 MainView(通常是 Window)和 MainViewModel,并让每个类树自己处理.

一个例子:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var window = new MainWindow();
        var vm = new MainViewModel();
        window.DataContext = vm;
        window.Show();
    }
}

但请记住,没有“一种正确的方法”可以做到这一点。不幸的是,你必须决定什么最适合你。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    相关资源
    最近更新 更多