【问题标题】:C# WPF How do you set up an "Update" button to change the contents of a row on a table?C# WPF 如何设置“更新”按钮来更改表格中一行的内容?
【发布时间】:2021-08-24 07:47:18
【问题描述】:

我是 WPF 的新手,我正在尝试弄清楚如何创建一个“更新”按钮,该按钮将显示表格上一行的所有内容,允许用户更改任何类别并保存新数据。

主窗口的外观:

然后当点击更新按钮时,会弹出一个类似这样的窗口。 :

你将如何制作第二个窗口?下面是我必须显示的没有“更新”按钮的主窗口。

**MainWindowxaml.cs**

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.Navigation;
using System.Windows.Shapes;

using System.Collections;
using System.IO;

namespace Sort_a_list
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public class Student
        {
            public string name
            {
                get;
                set;
            }
            public int age
            {
                get;
                set;
            }
            public string gender
            {
                get;
                set;
            }
            public string major
            {
                get;
                set;
            }
            public string classification
            {
                get;
                set;
            }

        }
        public MainWindow()
        {
            InitializeComponent();
            List<Student> user = new List<Student>();
            try
            {
                using (StreamReader sr = new StreamReader(@"C:\Users\justi\Documents\2021 Self Study\WPF C#\Samples.txt"))
                {
                    string line;
                    char[] sep = { ',' };
                    int length;
                    ArrayList rows = new ArrayList();

                    while ((line = sr.ReadLine()) != null)
                    {
                        string[] words = line.Split(sep);
                        length = words.Length;
                        rows.Add(words);

                    }
                    string[] columns;
                    for(int i = 1; i < rows.Count; i++)
                    {
                        columns = (string[])rows[i];
                        user.Add(new Student() { name = columns[0], age = Int16.Parse(columns[1]), gender = columns[2], major = columns[3], classification = columns[4] }); 
                    }
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("The file could not be read:");
                Console.WriteLine(e.Message);
            }

            sort.ItemsSource = user;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

        }
    }
}

请帮忙!非常感谢!

【问题讨论】:

  • 看看这个问题:stackoverflow.com/questions/2796470/wpf-create-a-dialog-prompt。我强烈建议您研究数据绑定并同时使用 MVVM 模式 - MVVM Light 和 Prism 等库会有所帮助。但是对于您的直接问题,您需要创建另一个 WPF 表单并将其显示为按钮单击处理程序中的模式对话框。
  • 显示编辑窗口的 XAML。

标签: c# wpf


【解决方案1】:

您将无法直接从 Window2 访问 Window1 的 DataGrid。 您也无法从 Window2 访问您的源集合(列表)以从那里修改它。

事实上,你有两种方法:

  • 使用外部数据库;
  • 创建学生的公共固定集合。

首先,无论如何我强烈建议您将一些 ID 字段添加到您的 Student 对象中,以便能够统一每个学生。

如果使用external database,您可以在单击Save 按钮时从Window2 调用类似"UPDATE students s SET s.name = @name, s.age = @age... WHERE s.ID = @id" 的内容。 @name, @age ... 是新的修改值

如果使用public fixed collection,您可以从程序的任何部分访问它。 当点击Window2保存按钮时,您可以通过学生ID在其中搜索学生并简单地编辑他。 Window2 关闭后,您只需通过重置 ItemsSource 来刷新 DataGrid 视图。 它可能看起来像这样:

学生班:

public class Student
{
    // Need to be unique for each student
    public int ID { get; private set; }

    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public string Major { get; set; }
    public string Classification { get; set; }

    public Student(int id)
    {
        ID = id;
        Name = "SomeName";
        Age = -1;
        Gender = "Unknown";
        Major = "Unknown";
        Classification = "None";
    }
    
    // May also be overloaded with id, id+name, id+name+age, id+name+age+gender etc
    public Student(int id, string name, int age, string gender, string major, string classification)
    {
        ID = id;
        Name = name;
        Age = age;
        Gender = gender;
        Major = major;
        Classification = classification;
    }

    // If you need some kind of string representation of Student
    public override string ToString()
    {
        return $"{ID},{Name},{Age},{Gender},{Major},{Classification}";
    }
} 

用于存储学生的固定和公共集合类:

public static class DB
{
    // Your actual Database, where Students would be stored
    private static readonly List<Student> students = new List<Student>();

    // You can get it by DB.Students from anywhere
    public static List<Student> Students { get { return students; } }

    // As I see you use a file as source for item collection.
    // You can add some Save() method to rewrite you existing
    // file with items from "database":
    // public static void Save()
    // {
    //    StringBuilder sb = new StringBuilder();
    //
    //    foreach (Student student in students)
    //    {
    //        sb.AppendLine(student.ToString());
    //    }
    //
    //    File.WriteAllText("PathToYourFile", sb.ToString());
    // }
    //
    // You should also override ToString method in Student class
    // with something like (in format you wish):
    // public override string ToString()
    // {
    //     return $"{ID},{Name},{Age},{Gender},{Major},{Classification}";
    // }
    } 
} 

在 Window1 更新按钮点击处理程序:

private void ButtonUpdate_Click(object sender, RoutedEventArgs e)
{
    // There should be selected only 1 item or use dataGrid.SelectedItems[0]
    if (dataGrid.SelectedItem is Student student)
    {
        // Pass selected Student to Window2
        // where user will edit it
        Window2 w2 = new Window2(student);

        // Subscribe to Closed window to refresh DataGrid view after Student editing
        w2.Closed += (s, a) =>
        {
            // Refresh the view of DataGrid by resetting its ItemsSource property
            dataGrid.ItemsSource = null;
            dataGrid.ItemsSource = DB.Students;
        };

        // Show update window
        w2.ShowDialog();
    }
}

还有某种 Window2:

public partial class Window2 : Window
{
    // Here would be a copy of Student object from Window1 
    // with which we would manipulate in Window2
    // while editing in its fields
    private readonly Student editableStudent = null;

    public Window2(Student student)
    {
        InitializeComponent();

        // Copy student object to store it in our Window2 
        // and be able to modify it not only from Constructor
        editableStudent = student;

        // Fill Window2 fields with existing Student values
        tbName.Text = student.Name;
        tbAge.Text = student.Age.ToString();
        tbGender.Text = student.Gender;
        tbMajor.Text = student.Major;
        tbClassification.Text = student.Classification;

        // Easy "on-the-fly" subscribe to each field TextChanged handlers to check, 
        // whether some data was changed/edited or not
        // and save it to editableStudent
        tbName.TextChanged += (s, a) => 
        {
            // Comparing value in field with existing Student's value
            if (tbName.Text != student.Name) // May also check for not empty / or for min input length
            {
                // Saving new value to a copied object of our Student
                editableStudent.Name = tbName.Text;
            } 
        };
        // Don't forget to check for integer value 
        // and convert in back to int: 
        // Convert.ToInt32(tbAge.Text)/int.Parse(tbAge.Text)/int.TryParse(tbAge.Text, out int age)
        tbAge.TextChanged += (sender, args) => { /* Do same as with Name */ };
        tbGender.TextChanged += (sender, args) => { /* Do same as with Name. */  };
        tbMajor.TextChanged += (sender, args) => { /* Do same as with Name */  };
        tbClassification.TextChanged += (sender, args) => { /* Do same as with Name */ };
    }

    private void ButtonSave_Click(object sender, RoutedEventArgs e)
    {
        // Find index of Student element in our "Database" (List)
        int index = DB.Students.FindIndex(x => x.ID == editableStudent.ID);

        if (index != -1)
        {
            // Update record in a collection if it was found
            DB.Students[index].Name = editableStudent.Name;
            DB.Students[index].Age = editableStudent.Age;
            DB.Students[index].Gender = editableStudent.Gender;
            DB.Students[index].Major = editableStudent.Major;
            DB.Students[index].Classification = editableStudent.Classification;

            // Instead of use 'editableStudent' field with copied in
            // constructor student's object, you can create it here
            // and fill with values from TextBoxes in Window2.
            // Or not create new Student object and fill new values
            // directly in "database" by index.
            // But you anyway need to store at least student's ID from
            // student's object, passed from Window1, to be able to 
            // find him in "database"
            // Student modifiedStudent = new Student(...);
            // modifiedStudent.Name = tbName.Text;
            // if (int.TryParse(tbAge.Text, out int age))
            //     modifiedStudent.Age = age;
            // ... 
            // DB.Students[index].Name = modifiedStudent.Name;
            // DB.Students[index].Age = modifiedStudent.Age;   
            // ...
            // or
            // DB.Students[index].Name = tbName.Text;
            // if (int.TryParse(tbAge.Text, out int age))
            //     DB.Students[index].Age = age;
            // ...         
        }
        else
        {
            // Or message user if not found
            MessageBox.Show("Student not found in Database (in a List of Students).");
        }

        // Close window after updating record in "Database"
        // DataGrid view we will refresh from Window1 after
        // Window2 close
        Close();
    }

    private void ButtonCancel_Click(object sender, RoutedEventArgs e)
    {
        // Do nothing with Student, just close
        Close();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    • 2019-06-02
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    相关资源
    最近更新 更多