将ViewModel绑定到多个窗口 [英] Binding ViewModel to multiple windows

查看:71
本文介绍了将ViewModel绑定到多个窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在重新编写Windows窗体项目,该项目的确为从vbnet到wpf c#的剪羊毛事件(不要问,这是新西兰的一项巨大运动)打分,并且遇到了一个我似乎无法解决的问题克服.

I'm re-writing my windows forms project that does scoring for sheep shearing events (don't ask, its a huge sport in New Zealand) from vbnet to wpf c# and have struck a problem that I can't seem to overcome.

我有两个窗户.一个是在源窗口中键入内容的源窗口(例如当前事件名称),另一个窗口将以闪烁的方式显示此信息,以将其投影到屏幕上(因此将在第二台监视器上)以及一些其他数据通过网络通过XML输入.我已将其设置为MVVM,并将ViewModel和Model设置为单独的项目.

I have two windows. One is the source window where you type things in (like the current event name), and the other window will display this information in a flash way for projection onto a screen (so will be on a second monitor) along with some other data coming in via XML over the network. I have set it up as MVVM with a ViewModel and a Model as separate projects.

在主窗口上,我可以很好地绑定控件,如果在一个文本框中键入内容,则如果绑定到同一事物,它会立即出现在另一个文本框中.但是,在第二个窗口中,我将控件绑定到同一件事,并且它没有更新.

On my Main window, I can bind controls fine and if I type in one text box it immediately appears in another text box if it is bound to the same thing. However, on a second window, I have bound a control to the same thing and it is not updating.

我已经在这个圈子中转了一个星期,网上的每个示例都显示了如何在一个运行良好的窗口上执行该操作,但是缺少两个窗口示例.

I've been going around in circles on this for a week, every example on the net shows how to do it on One window which I have got working fine, but there is a lack of two window examples.

这就是我所拥有的...

Here is what I have...

这是在我的ViewModel项目中

This is in my ViewModel project

namespace SheepViewModel
{
public class SheepViewModel : INotifyPropertyChanged


{
    private string _CurrentEventName;
    static SheepViewModel _details;

    public string CurrentEventName
    {
        get { return _CurrentEventName; }
        set
        {
            _CurrentEventName = value;
            OnPropertyChanged("CurrentEventName");
        }
    }

    public static SheepViewModel GetDetails()
    {
        if (_details == null)
            _details = new SheepViewModel();
        return _details;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string prop)
    {
        if (PropertyChanged != null)
             PropertyChanged(this, new PropertyChangedEventArgs(prop));
            Console.WriteLine("Test");
            }     
    }
}

然后我有一个主窗口,除了要打开第二个窗口的行之外,没有任何实际代码,我们将转到...

Then I have a main window, there is no real code behind other than a line to open a second window which we will get to...

 public MainWindow()
    {
        ScoreScreen SW = new ScoreScreen();
        SW.Show();
        InitializeComponent();
    }

然后使用XAML

<Window x:Class="Sheep_Score_3._1.MainWindow"
    xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:SheepViewModel;assembly=SheepViewModel"
    mc:Ignorable="d"
    Title="MainWindow" Height="433.689" Width="941.194">
<Window.DataContext>
    <vm:SheepViewModel/>
</Window.DataContext>
<Window.Resources>
<Grid Margin="0,0,0,0">
<TextBox x:Name="CurrentEventName" Height="23" Margin="131.01,163.013,0,0" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalAlignment="Left" Width="327.151" Text="{Binding CurrentEventName, Mode=TwoWay}"/>
    <TextBox Text="{Binding CurrentEventName, Mode=TwoWay}" Margin="39.605,0,0,108.567" Height="49.111" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="399" />
</Grid>

上面的代码都可以正常工作,如果我在第一个文本框中键入文本,它将显示在第二个文本框中.如果我将console.writeline放在notify部分中,那么我可以看到它被击中并进行了更新.

The above code all works fine, if I type text in the first textbox it appears in the second text box. If I put a console.writeline in the notify part then I can see it hitting it and updating.

现在我添加第二个窗口,设置方式完全相同...

Now I add a second window, setup exactly the same way...

<Window x:Class="Sheep_Score_3._1.ScoreScreen"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:SheepViewModel;assembly=SheepViewModel"
    mc:Ignorable="d"
    Title="ScoreScreen" Height="300" Width="300">
<Window.DataContext>
    <vm:SheepViewModel/>
</Window.DataContext>
<Grid>
    <TextBox x:Name="textBlock" HorizontalAlignment="Left" Margin="79.374,116.672,0,0" TextWrapping="Wrap" Text="{Binding CurrentEventName, Mode=TwoWay}" VerticalAlignment="Top"/>
</Grid>

同样,在这之后没有真实的代码.

Again, no real code behind in this.

奇怪的是,如果我以两种方式制作此控件并键入它,我可以看到它击中了相同的notify部分,但它没有更新其他窗口.

The strange thing, is if I make this control two way and type in it, I can see it hitting the same notify section, but it is not updating the other window.

我不确定我在这里缺少什么,因此非常感谢您为我指明正确的方向.

I'm not sure what I am missing here so any help in pointing me in the right direction would be much appreciated.

推荐答案

这是因为两个窗口都必须共享与ViewModel完全相同的实例.

您的所有属性都是实例属性,例如

All your properties are instance properties, like

public string CurrentEventName { get { // snip

,因此所有值对于每个实例都是不同的.您正在创建两个实例,每个窗口一个.

and therefore all values are distinct to each instance. You're creating two instances, one for each window.

<Window x:Class="Sheep_Score_3._1.MainWindow"
    xmlns:blah="http://inurxamlskippinurschemas.org">
    <Window.DataContext>
        <vm:SheepViewModel/>
    </Window.DataContext>

那是一个实例,另外一个是

That's one instance, and here's the other

<Window x:Class="Sheep_Score_3._1.ScoreScreen"
        xmlns:blah="http://yaddayaddawhocares.derp">
    <Window.DataContext>
        <vm:SheepViewModel/>
    </Window.DataContext>

请记住,xaml只是将其反序列化为对象图的标记.您有两个不同的标记文件,它们包含其中描述的所有内容的不同实例.

Remember, xaml is just markup that is deserialized into an object graph. You've got two different markup files, they contain distinct instances of everything described within them.

这没有错,并且拥有带有实例属性的视图模型也没有错.实际上,这是使用静态和静态绑定的首选方法.

There's nothing wrong with this, and nothing wrong with having a view model with instance properties. In fact, that's the preferred way over using statics and static bindings.

幸运的是答案很简单.您需要将两个窗口传递给视图模型的相同实例.

The answer is luckily simple. You need to hand both windows the same instance of your view model.

首先,从两个窗口中删除所有< Window.DataContext> 废话.那不是给你的.现在,只需将您的构造函数更改为

First, remove all the <Window.DataContext> nonsense from both of your windows. That's not for you. Now, simply change your constructor to

public MainWindow()
{
    var viewModel = new SheepViewModel();
    ScoreScreen SW = new ScoreScreen();
    SW.DataContext = viewModel;
    SW.Show();
    InitializeComponent();
    //NOTICE!  After Init is called!
    DataContext = viewModel;
}

您完成了.

这篇关于将ViewModel绑定到多个窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆