将对象从子窗口传回 MainWindow

Passing an object back to MainWindow from a subwindow

提问人:Rembie01 提问时间:7/25/2022 最后编辑:Rembie01 更新时间:7/26/2022 访问量:67

问:

我正在尝试创建一个小数据库程序,您可以在其中添加、修改和删除新闻网站的文章。有一个带有 DataGrid 的 MainWindow 来显示所有文章。按下“添加”按钮后,将打开一个新窗口,供您编辑新创建的文章。或者可以按下修改按钮来编辑当前选择的文章。如何将文章传递回 MainWindow 以将其添加到 ObservableCollection/modify ObservableCollection?

public partial class MainWindow : Window
    {
        private int lastIdArtikel = 0;
        private Artikel currentSelection = null; 
        private ObservableCollection<Artikel> ArtikelDatabase = new ObservableCollection<Artikel>();

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            Artikel nieuwArtikel = new Artikel(++lastIdArtikels);
            ArtikelDatabase.Add(nieuwArtikel);
            ArtikelVenster artikelVenster = new ArtikelVenster(ref nieuwArtikel);
            artikelVenster.Show();
        }

        private void Modify_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                ArtikelVenster artikelVenster = new ArtikelVenster(ref huidigeSelectie);
                artikelVenster.Show();
            }
            catch (NullReferenceException exception)
            {
                Console.WriteLine(exception.StackTrace);
            }            
        }

 public partial class ArtikelVenster : Window
    {
        public Artikel artikel { get; private set; }
        public int id { get; private set; }
        public string title { get; private set; }
        public object category { get; private set; }
        public string nameJournalist { get; private set; }
        public bool mayBePublished { get; private set; }
        public bool isPublished { get; private set; }
        public string content { get; private set; }
        public int length { get; private set; }

        public ArtikelVenster(ref Artikel huidigArtikel)
        {
            InitializeComponent();
            artikel = huidigArtikel;
            try
            {
                LaadData();
            }
            catch (NullReferenceException exception)
            {
                Console.WriteLine(exception.StackTrace);
            }
            CategorieBox.SelectedIndex = 2;
        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void LaadData()
        {
            IdLabel.Content = artikel.id;
            DatumLabel.Content = artikel.creationDate.ToString();
            TitelBox.Text = artikel.title;
            CategorieBox.SelectedItem = artikel.category;
            NaamJournalistBox.Text = artikel.nameJournalist;
            IsGepubliceerdToggle.IsChecked = artikel.isPublished;
            MagGepubliceerdWordenToggle.IsChecked = artikel.mayBePublished;
            if (artikel.content == null)
            {
                InhoudBox.Selection.Text = "";
            }
            else
            {
                InhoudBox.Selection.Text = artikel.content;
            }
        }

        private void Confirm_Click(object sender, RoutedEventArgs e)
        {
            if (artikel == null)
            {
                Artikel nieuwArtikel = new Artikel(id);
                nieuwArtikel.updateArtikel(title, category, nameJournalist, mayBePublished, isPublished, content, length);
                artikel = nieuwArtikel;
            }
            else
            {
                artikel.updateArtikel(title, category, nameJournalist, mayBePublished, isPublished, content, length);
            }
            this.Close();
        }

        private void TitelBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            title = TitelBox.Text;
        }

        private void CategorieBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            category = CategorieBox.SelectedItem;
        }

        private void NaamJournalistBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            nameJournalist = NaamJournalistBox.Text;
        }
    }
    public class Artikel
    {
        public int id { get; private set; }
        public string title { get; private set; }
        public object category { get; private set; }
        public string nameJournalist { get; private set; }
        public bool mayBePublished { get; private set; }
        public bool isPublished { get; private set; }
        public string content { get; private set; }
        public int length { get; private set; }
        public DateTime creationDate { get; private set; }

        public Artikel(int id)
        {
            this.id = id;
            this.creationDate = DateTime.Now;
        }

        public void updateArtikel(string title, object category, string nameJournalist, bool mayBePublished, bool isPublished, string content, int length)
        {
            this.title = title;
            this.category = category;
            this.nameJournalist = nameJournalist;
            this.mayBePublished = mayBePublished;
            this.isPublished = isPublished;
            this.content = content;
            this.length = length;
        }
    }
}

为了使其更具可读性,省略了某些部分。如果需要更多信息,请告诉我。

C# WPF 按引用传递

评论

0赞 yassinMi 7/25/2022
通过在 ArtikelVenster 类中创建一个公共属性,该属性将携带结果对象引用,然后从调用方访问它
0赞 Rembie01 7/26/2022
@yassinMi已经有一个公共的 Artikel 属性,但是当 ArtikelVenster 关闭/按下按钮时,我需要某种事件来让 MainWindow 知道将 Artikel 添加到 ObservableCollection。对不起,如果这还不完全清楚。
0赞 Rembie01 7/26/2022
只有当单击确认按钮时,我才能确保输入所有字段,并且可以将 Artikel 添加到列表中

答:

1赞 yassinMi 7/26/2022 #1

在窗口类中声明事件

public event EventHandler<Artikel> Confirmed; 

在确认按钮单击处理程序中调用它

//artikel being the object that you want to send back to the main window  
 
Confirmed?.Invoke(this,artikel);

您可以从调用方添加侦听器:

artikelVenster.Confirmed+=(s, e) =>{//do something with e };
artikelVenster.Show();

评论

1赞 Mathieu Guindon 7/26/2022
按原样,这将需要 Artikel 继承 EventArgs,这可能不是一个好主意。最好创建一个专用的 ArtikelEventArgs 来封装 Artikel 引用。不过,整体方法在我看来不错:+1!
0赞 yassinMi 7/26/2022
这是框架本身的限制,还是只是更好的方法?因为当我使用任何类型时,我不会收到任何编译或运行时错误/警告
1赞 Mathieu Guindon 7/26/2022
啊,你是对的,没有强制继承的通用约束 - 但是是的,这完全是一种最佳实践:这样,如果/当处理程序需要任何其他信息时,事件的类型及其处理程序的签名不需要更改,只需将新成员添加到 EventArgs 派生的类中,您就完成了。TEventArgsSystem.EventArgs