如何从 WPF 中的另一个窗口绑定到 MainWindow 中的控件?

Posted

技术标签:

【中文标题】如何从 WPF 中的另一个窗口绑定到 MainWindow 中的控件?【英文标题】:How can I bind to a control in the MainWindow from another window in WPF? 【发布时间】:2013-01-06 01:09:21 【问题描述】:

基本上,我的问题已经出现在标题中: 当我有如下 MainWindow 时:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:easycache"
        xmlns:map="clr-namespace:MapControl;assembly=MapControl.WPF"
        x:Class="easycache.MainWindow"
        x:Name="MainWindow1"
        Title="easycache"
        Height="600"
        Width="850">
  <map:Map Grid.Column="2"
           Grid.Row="1"
           Name="map"
           IsManipulationEnabled="True"
           LightForeground="Black"
           LightBackground="White"
           DarkForeground="White"
           DarkBackground="#FF3F3F3F"
           Center="0.0,0.0"
           ZoomLevel="0.0"
           TileLayer="Binding Source=StaticResource TileLayersView, Path=CurrentItem" />

在我的窗口 2 中,我有:

<map:Map Name="map" IsManipulationEnabled="False"
                 LightForeground="Black" LightBackground="White" DarkForeground="White" DarkBackground="#FF3F3F3F"
                 Center="0.0,0.0" ZoomLevel="Binding ?????">

我想将 Window2 中地图的 ZoomLevel 绑定到我的 MainWindow 中地图的 ZoomLevel。我怎样才能做到这一点?

问候, 亚洛金

【问题讨论】:

如果你在做 MVVM,那么应该通信的是 ViewModel。如果你不是更简单。告诉我哪个,以便我可以给出正确的答案,问候 我同意 Hannish 的观点 - 有几种不同的方法可以做到这一点,具体取决于您的程序的架构方式。你在任何地方都使用 MVVM、ViewModels 和 Bindings 吗?还是只是直接事件和代码隐藏之类的? 感谢您的快速回答,我没有使用 MVVM!那你能给我举个例子吗? 怎么了? @Hannish,拜托,你能给我举个例子吗?我真的不知道该怎么办...... 【参考方案1】:

在您的 MainWindow 代码隐藏中创建一个带有公共 get 访问器的公共属性,如下所示:

private double _mapZoom;
public double MapZoom //I assume that ZoomLevel is of type double, if not use the correct type

    get  return _mapZoom; 
    set  _mapZoom = value; OnPropertyChanged("MapZoom"); 

您必须在您的 MainWindow 中实现 INotifyPropertyChanged 接口(到处都有一百万个示例,这里无需赘述)。

然后,将地图的 ZoomLevel 属性绑定到 MapZoom 属性,如下所示:

<map:Map Name="map" ZoomLevel="Binding RelativeSource=RelativeSource Self, Path=MapZoom, Mode=TwoWay"/>

为此,Window 的 DataContext 必须是 Window 本身,在 Window 的构造函数中需要一行:

    public MainWindow()
    
        InitializeComponent();
        this.DataContext = this; //add this line
    

您需要一种方法让第二个窗口调用主窗口,因此您可以创建一个静态属性来返回主窗口中的当前实例:

    private static MainWindow _instance;
    public static MainWindow Instance
    
        get
        
            if (_instance == null)
                _instance = new MainWindow();
            else
                _instance = this;

            return _instance;
        
     //you have to make sure to create ONE instance of MainWindow before getting this property, and not to create more instances elsewhere

现在您将在 MainWindow 中公开一个公共属性,该属性绑定到地图的缩放。

因此,在您的第二个窗口中创建一个指向该主窗口实例的属性:

   public MainWindow Main  get  return MainWindow.Instance; 

最后,您可以将第二张地图的缩放绑定到作为 Main 成员的公共属性 MapZoom:

<map:Map Name="map2" ZoomLevel="Binding RelativeSource=RelativeSource Self, Path=Main.MapZoom, Mode=TwoWay"">

在这个绑定中,“Main”是通过window2的public属性引用MainWindow实例(在window2中也设置this.DataContext = this;),并访问.MapZoom属性。

默认情况下,您在 XAML 中创建的所有对象都是私有的,因此您必须使用带有 get/set 访问器的公共属性显式公开它们,以使它们可以从外部访问。

让我知道这是否可行,我没有创建应用程序来测试代码。问候!

【讨论】:

感谢您的回答,但在等待回答时,我尝试了其他尝试来实现这一点:我现在创建了一个具有 currentzoom 属性的类,并两次绑定到该属性。 这是一个 WPF 反模式,应该避免:this.DataContext = this;相反,您应该查看 RelativeSource 在应用于绑定时的工作方式。 @user3690202 你应该详细说明为什么一个窗口不能是它自己的数据上下文,你应该做的是发布你自己的答案,展示如何按照你的方式去做。否定不是这里的方法。

以上是关于如何从 WPF 中的另一个窗口绑定到 MainWindow 中的控件?的主要内容,如果未能解决你的问题,请参考以下文章

无法数据绑定滑块 WPF 的值 [重复]

如何将listView的selectedItem值传递到wpf MVVM中的另一页

WPF MVVM绑定窗口图标到视图模型中的属性

如何自动更新 WPF DataGrid 和 xml 之间的绑定

WPF:将组件的高度绑定到另一个组件的高度

WPF MVVM从入门到精通2:实现一个登录窗口