简体   繁体   中英

INotifyPropertyChanged with 2 Windows

I have a simple WPF application with 2 windows. I am trying to update a textblock and a checkbox on MainWindow when a user input something on SubWindow.

There are two variables that I set to pass values between windows.

Properties.Settings.Default.strText
Properties.Settings.Default.isChecked

MainWindow.xaml

<Window x:Class="PropertyChangedExample.MainWindow"
        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:local="clr-namespace:PropertyChangedExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="400"
        Focusable="False">
    <Grid>
        <TextBlock x:Name="TxtBlock" Text="{Binding TxtBinding}" Width="200" Height="30" Margin="0,100,0,0"/>
        <CheckBox IsChecked="{Binding IsChecked}" Width="25" Height="25" />
    </Grid>
</Window>

MainWindow.xaml.cs

using System.ComponentModel;
using System.Windows;

namespace PropertyChangedExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            SubWindow subWindow = new SubWindow();
            subWindow.Show();

            DataContext = new DataContextExample();
        }
    }

    public class DataContextExample : INotifyPropertyChanged
    {
        public string TxtBinding
        {
            get { return Properties.Settings.Default.strText; }
            set
            {
                Properties.Settings.Default.strText = value;
                OnPropertyChanged(nameof(TxtBinding));
            }
        }

        public bool IsChecked
        {
            get { return Properties.Settings.Default.isChecked; }
            set
            {
                Properties.Settings.Default.isChecked = value;
                OnPropertyChanged(nameof(IsChecked));
            }
        }

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

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

SubWindow.xaml

<Window x:Class="PropertyChangedExample.SubWindow"
        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:local="clr-namespace:PropertyChangedExample"
        mc:Ignorable="d"
        Title="SubWindow" Height="100" Width="250">
    <Grid>
        <TextBox KeyUp="Window_KeyUp" x:Name="TxtBox" Width="200" Height="30" />
    </Grid>
</Window>

SubWindow.xaml.cs

using System.Windows;
using System.Windows.Input;

namespace PropertyChangedExample
{
    /// <summary>
    /// Interaction logic for SubWindow.xaml
    /// </summary>
    public partial class SubWindow : Window
    {
        public SubWindow()
        {
            InitializeComponent();
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                Properties.Settings.Default.strText = TxtBox.Text;
            }
            else if (e.Key == Key.LeftCtrl)
            {
                Properties.Settings.Default.isChecked = true;
            }
            else if (e.Key == Key.LeftShift)
            {
                Properties.Settings.Default.isChecked = false;
            }

        }
    }
}

When a user enter anything on the textbox on SubWindow, the textblock on MainWindow should be updated. Also, the checkbox should be either checked and unchecked if a user press either left ctrl or shift key. So far, nothing happens. What am I missing here?

You need to pass the DataContext to your second window, or else it has no way of knowing about the data used in your MainWindow . This can be done in the second window's constructor.

DataContextExample myContext;
public SubWindow(DataContextExample context)
{
    myContext = context;
    DataContext = myContext;
    InitializeComponent();
}

Then call it like so in from your MainWindow

public MainWindow()
{
       InitializeComponent();

       DataContextExample context = new DataContextExample();

       SubWindow subWindow = new SubWindow(context);
       subWindow.Show();

       DataContext = context;
}

Also, in your second window you are changing Properties.Setting.Default values directly, but you need to change the DataContext value.

private void Window_KeyUp(object sender, KeyEventArgs e)
{
     if (e.Key == Key.Enter)
     {
           myContext.strText = TxtBox.Text;           
     }
     //....
}

The best solution i can see for this kind of situation is messagin or know as Publisher/Subscriber pattern, in your sub window you create an event and publish it to whatever lessner (subscriber). here is a simple example: https://www.c-sharpcorner.com/UploadFile/pranayamr/publisher-or-subscriber-pattern-with-event-or-delegate-and-e/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM