WPF使用一个ViewModel来操作两个独立窗口中的TextBoxes。

huangapple go评论73阅读模式
英文:

WPF using one VIewModel to manipulate TextBoxes in two seperate windows

问题

I am having a problem with binding data. I'd like to bind text of TextBox which is in MainWindow to another TextBox which is in ChildWindow. While being in MainWindow, user can input a string into that TextBox. ChildWindow will be only displaying some data. I've managed to bind the TextBox from MainWindow and I can see that while debugging it hits MainWindowViewModel, However there's no effect on the ChildWindow.

My App.xaml.cs looks like this:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var window = new MainWindow() { DataContext = new MainWindowViewModel() };
        window.Show();

        base.OnStartup(e);
    }
}

then MainWindow creates an instance of ChildWindow and they both use the same ViewModel as below:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        var viewModel = new MainWindowViewModel();
        ChildWindow childWindow = new ChildWindow();
        childWindow.DataContext = viewModel;
        childWindow.Show();
        InitializeComponent();
        DataContext = viewModel;
    }
}

MainWindowViewModel:

public class MainWindowViewModel : ViewModelBase
{
    public string _firstTeamName { get; set; }
    public string FirstTeamName
    {
        get { return _firstTeamName; }
        set
        {
            _firstTeamName = value;
            OnPropertyChanged(nameof(FirstTeamName));
        }
    }
}

ViewModelBase:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }
}

Binding in MainWindow.xaml:

<TextBox x:Name="firstTeam" Height="30" VerticalAlignment="Top" Text="{Binding FirstTeamName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

Binding in ChildWindow.xaml:

<TextBlock Text="{Binding FirstTeamName}" FontSize="24"></TextBlock>
英文:

I am having a problem with binding data. I'd like to bind text of TextBox which is in MainWindow to another TextBox which is in ChildWindow. While being in MainWindow, user can input a string into that TextBox. ChildWindow will be only displaying some data. I've managed to bind the TextBox from MainWIndow and I can see that while debugging it hits MainWindowViewModel, However there's no effect on the ChildWindow.

My App.xaml.cs looks like this:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var window = new MainWindow() { DataContext = new MainWindowViewModel() };
        window.Show();

        base.OnStartup(e);
    }
}

then MainWIndow creates an instance of ChildWindow and they both use same ViewModel as below:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        var viewModel = new MainWindowViewModel();
        ChildWindow childWindow = new ChildWindow();
        childWindow.DataContext = viewModel;
        childWindow.Show();
        InitializeComponent();
        DataContext = viewModel;
    }
}

MainWindowViewModel:

public class MainWindowViewModel : ViewModelBase
{
    public string _firstTeamName { get; set; }
    public string FirstTeamName
    {
        get { return _firstTeamName; }
        set
        {
            _firstTeamName = value;
            OnPropertyChanged(nameof(FirstTeamName));
        }
    }
}

ViewModelBase:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }
}

Binding in MainWindow.xaml:

&lt;TextBox x:Name =&quot;firstTeam&quot;  Height=&quot;30&quot; VerticalAlignment=&quot;Top&quot; Text =&quot;{Binding FirstTeamName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot;/&gt;

Binding in ChildWindow.xaml:

&lt;TextBlock Text =&quot;{Binding FirstTeamName}&quot; FontSize=&quot;24&quot;&gt;&lt;/TextBlock&gt;

答案1

得分: 0

你的错误是将 MainWindow.DataContext 设置了两次。

  1. MainWindow 构造函数内。
  2. App.OnStartUp 中使用 var window = new MainWindow() { DataContext = new MainWindowViewModel() };

这里发生了什么?

  • new MainWindow() 会调用构造函数并将 MainWindowChildWindowDataContext 设置为相同的 MainWindowViewModel 实例。
  • { DataContext = new MainWindowViewModel() } 会用一个新的 MainWindowViewModel 实例覆盖 MainWindowDataContext

现在这两个窗口有两个不同的 ViewModel 实例,将不会按预期工作。

这应该修复它

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var window = new MainWindow() 
        { 
            // DataContext = new MainWindowViewModel() 
        };
        window.Show();

        base.OnStartup(e);
    }
}
英文:

Your mistake is to set the MainWindow.DataContext twice.

  1. Inside the contructor of MainWindow
  2. In App.OnStartUp with var window = new MainWindow() { DataContext = new MainWindowViewModel() };

What does happen here?

  • new MainWindow() will call the constructor and set the DataContext of MainWindow and ChildWindow to the same instance of MainWindowViewModel.
  • { DataContext = new MainWindowViewModel() } will overwrite the DataContext of MainWindow with a new instance of MainWindowViewModel.

Now the two windows have two different instances of the ViewModel and will not work as expected.

This should fix it

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var window = new MainWindow() 
        { 
            // DataContext = new MainWindowViewModel() 
        };
        window.Show();

        base.OnStartup(e);
    }
}

huangapple
  • 本文由 发表于 2023年8月5日 08:36:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76839719.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定