WPF 在克隆窗口之间传递数据

本文关键字:数据 之间 窗口 WPF | 更新日期: 2023-09-27 18:31:16

我有一个MainWindow,MainWindow中有一个按钮可以打开ClientWindow。

private void btnMakeClient_Click(object sender, RoutedEventArgs e)
        {
            ClientWindow window = new ClientWindow();           
            window.Show();
        }

例如,如果我点击 3 次,那么它会打开 3 个客户端窗口(chatWindow)。如何在这些克隆窗口之间传递数据(文本)?我的意思是我在ClientWindow(chatWindow)中写"嗨,你好吗?",它也出现在另一个窗口中。

我认为如果我使用 MainWindow 构造函数从 ClientWindow 传递数据(文本)并使用 ClientWindow 构造函数将其取回,则会解决我的问题,但事实并非如此。这是我的代码

主窗口:

 public partial class MainWindow : Window
    {
        public string TextContent { get; set; }
        public MainWindow()
        {
            InitializeComponent();
        }
        public MainWindow(string txtContext)
        {
            InitializeComponent();
            TextContent = txtContext;
            ClientWindow window = new ClientWindow(TextContent);
        }
        private void btnMakeClient_Click(object sender, RoutedEventArgs e)
        {            
            ClientWindow window = new ClientWindow();
            window.Show();
        }
    }

客户端窗口:

 public partial class ClientWindow : Window
    {
    public string Chatcontent { get; set; }
    public ClientWindow()
    {
        InitializeComponent();
    }
    public ClientWindow(string chatContent)
    {
        InitializeComponent();
        Chatcontent = chatContent;
        if (chatContent != string.Empty)
        {
            this.txtContent.Text += Environment.NewLine + Chatcontent;
            txtChat.Clear();
        }            
    }
    private void btnSend_Click(object sender, RoutedEventArgs e)
    {
        MainWindow window = new MainWindow(txtChat.Text);
    }
}

WPF 在克隆窗口之间传递数据

这就是 MVVM 闪耀的地方。创建一个 ViewModel 对象,其中包含一个 String 属性和一个用于向此属性添加文本的命令,然后在客户端窗口中,只需使用要添加为参数的文本调用此命令。

请注意,我使用此处所述的 DelegateCommand,但您也可以使用 RelayCommand。

视图模型

public class YourViewModel : INotifyPropertyChanged {
    private String _textContent;
    public String TextContent {
        get {return _textContent;}
        set {
            _textContent = value;
            OnPropertyChanged("TextContent");
        }
    }
    private DelegateCommand _cmdAddTextToChat;
    /// <summary>
    /// Add text to TextContent
    /// </summary>
    public DelegateCommand CmdAddTextToChat {
        get { return _cmdAddTextToChat ?? (_cmdAddTextToChat = new DelegateCommand(AddTextToChat)); }
    }
    private void AddTextToChat(Object parameter) {
        TextContent += (String)parameter;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName) {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
public partial class MainWindow : Window
{
    private YourViewModel _vm = new YourViewModel ();
    public MainWindow()
    {
        InitializeComponent();
    }
    public MainWindow(string txtContext)
    {
        InitializeComponent();
        _vm.TextContent = txtContext;
        ClientWindow window = new ClientWindow() {DataContext = _vm};
    }
    private void btnMakeClient_Click(object sender, RoutedEventArgs e)
    {            
        ClientWindow window = new ClientWindow() {DataContext = _vm};
        window.Show();
    }
}

public partial class ClientWindow : Window
    public ClientWindow()
    {
        InitializeComponent();  
    }
}

客户端窗口 xaml:

<DockPanel>
    <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
        <TextBox x:Name="InputTextBox"/>
        <Button Command="{Binding CmdAddTextToChat, Mode=OneWay}" CommandParameter="{Binding ElementName=InputTextBox, Path=Text}">
    </StackPanel>
    <TextBlock DockPanel.Dock="Top" Text="{Binding TextContent, Mode=OneWay}"/>
</DockPanel>

编辑:没有数据上下文

如果您不想设置 DataContext,您可以使用另一个 DP(可以使用 Tag,也可以创建一个新 DP):

#region ViewModelObject 
public YourViewModel ViewModelObject
{
    get { return (YourViewModel)GetValue(ViewModelObjectProperty); }
    set { SetValue(ViewModelObjectProperty, value); }
}
private readonly static FrameworkPropertyMetadata ViewModelObjectMetadata = new FrameworkPropertyMetadata {
};
public static readonly DependencyProperty ViewModelObjectProperty = 
    DependencyProperty.Register("ViewModelObject", typeof(YourViewModel), typeof(ClientWindow), ViewModelObjectMetadata);
#endregion

在您的点击事件中

private void btnMakeClient_Click(object sender, RoutedEventArgs e)
{            
    ClientWindow window = new ClientWindow() {YourViewModelObject = _vm};
    window.Show();
}

您可以使用 Text 属性为消息创建一个类,并在此类中实现 INotifyPropertyChanged。然后将此类的实例存储在 MainWindow 中,并将其传递给 ClientWindow 的构造函数。将其设置为 DataContext 并创建与 Text 属性的绑定(例如,在 TextBox 中)。更新 Text 属性时,其他窗口将看到此更改。