WPF中如何从次级窗口向主窗口传值修改待办任务名称
待办列表跨窗口编辑TaskName为空值问题
开发待办列表项目时,希望通过次级窗口(EditWindow)的TextBox修改主窗口(DemoMainWindow)ObservableCollection中的TaskName字符串值。同一窗口内修改可正常生效,但从次级窗口操作时,目标编辑项会变为空值。
主窗口(DemoMainWindow)代码
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using ToDoList.ViewModels; using ToDoList.Model; namespace ToDoList { /// <summary> /// Interaction logic for DemoMainWindow.xaml /// </summary> public partial class DemoMainWindow : Window { private ViewModel _viewModel; public string? EditedTaskName { get; set; } public DemoMainWindow() { InitializeComponent(); TxtUCEnteredTask.txtLimitedInput.Text = "Do the dishes"; _viewModel = new ViewModel(); DataContext = _viewModel; } private void BtnAddTask_Click(object sender, RoutedEventArgs e) { _viewModel.Tasks.Add(new TaskModel() { TaskName = TxtUCEnteredTask.txtLimitedInput.Text }); } private void BtnDeleteTask_Click(object sender, RoutedEventArgs e) { if(LstBoxTasks.SelectedItem != null) { #pragma warning disable CS8604 // Possible null reference argument. _ = _viewModel.Tasks.Remove(item: LstBoxTasks.SelectedItem as TaskModel); #pragma warning restore CS8604 // Possible null reference argument. } } private void BtnHelp_Click(object sender, RoutedEventArgs e) { HelpWindow helpWindow = new HelpWindow(); helpWindow.Show(); } private string? GetEditedTaskName() { return EditedTaskName; } private void BtnEditTask_Click(object sender, RoutedEventArgs e) { if (LstBoxTasks.SelectedItem != null) { EditWindow editWindow = new EditWindow(); editWindow.Show(); //_viewModel.Tasks[LstBoxTasks.SelectedIndex].TaskName = editedTaskName; } } } }
次级窗口(EditWindow)代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace ToDoList { /// <summary> /// Interaction logic for EditWindow.xaml /// </summary> public partial class EditWindow : Window { public EditWindow() { InitializeComponent(); var DemoMainWindow = this.DataContext; } private void BtnEdit_Click(object sender, RoutedEventArgs e) { ((DemoMainWindow)Application.Current.MainWindow).EditedTaskName = EditTextBox.Text; // _viewModel.Tasks[LstBoxTasks.SelectedIndex].TaskName = TxtUCEnteredTask.txtLimitedInput.Text; } } }
问题原因及解决方案
问题根源
当前代码仅把输入的文本赋值给主窗口的EditedTaskName属性,但没有将这个值同步到ObservableCollection中选中的TaskModel对象;同时,次级窗口没有获取到主窗口中选中的任务项,也没有在编辑完成后触发主窗口更新任务名称的逻辑。
解决方案1:直接传递选中的TaskModel对象
修改主窗口的BtnEditTask_Click方法,将选中的任务项传递给EditWindow:
private void BtnEditTask_Click(object sender, RoutedEventArgs e) { if (LstBoxTasks.SelectedItem is TaskModel selectedTask) { EditWindow editWindow = new EditWindow(selectedTask); editWindow.ShowDialog(); } }
修改EditWindow的构造函数,接收并绑定选中的TaskModel:
private readonly TaskModel _selectedTask; public EditWindow(TaskModel selectedTask) { InitializeComponent(); _selectedTask = selectedTask; EditTextBox.Text = selectedTask.TaskName; } private void BtnEdit_Click(object sender, RoutedEventArgs e) { _selectedTask.TaskName = EditTextBox.Text; Close(); }
解决方案2:共享ViewModel
让EditWindow直接绑定到主窗口的ViewModel,并传递选中任务的索引:
主窗口打开EditWindow时传递参数:
private void BtnEditTask_Click(object sender, RoutedEventArgs e) { if (LstBoxTasks.SelectedIndex != -1) { EditWindow editWindow = new EditWindow(_viewModel, LstBoxTasks.SelectedIndex); editWindow.ShowDialog(); } }
EditWindow接收ViewModel和索引:
private readonly ViewModel _viewModel; private readonly int _selectedIndex; public EditWindow(ViewModel viewModel, int selectedIndex) { InitializeComponent(); _viewModel = viewModel; _selectedIndex = selectedIndex; EditTextBox.Text = _viewModel.Tasks[selectedIndex].TaskName; } private void BtnEdit_Click(object sender, RoutedEventArgs e) { _viewModel.Tasks[_selectedIndex].TaskName = EditTextBox.Text; Close(); }
关键注意事项
确保TaskModel实现INotifyPropertyChanged接口,这样修改TaskName时UI才会自动更新:
public class TaskModel : INotifyPropertyChanged { private string _taskName; public string TaskName { get => _taskName; set { _taskName = value; OnPropertyChanged(nameof(TaskName)); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
内容的提问来源于stack exchange,提问作者Savage's Project
相关产品推荐
相关产品推荐

