[英]C# WPF How do you set up an "Update" button to change the contents of a row on a table?
I am new to WPF and I am trying to figure out how to create an "Update" button that will show all the contents of a row on a table, allowing the user to change any category and save the new data.我是 WPF 的新手,我试图弄清楚如何创建一个“更新”按钮,该按钮将显示表格上一行的所有内容,允许用户更改任何类别并保存新数据。
What the main window would look like:主要的 window 会是什么样子:
Then when the update button is clicked, a window looking like this would pop up.然后当点击更新按钮时,会弹出一个看起来像这样的 window。 :
:
How would you make the second window?你将如何制作第二个 window? Down below is what I have to show the main window without an "update" button.
下面是我必须显示的主要 window 没有“更新”按钮。
**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)
{
}
}
}
Please help!请帮忙! Thank you very much!
非常感谢!
You won't be able to access your Window1's DataGrid from Window2 directly.您将无法直接从 Window2 访问 Window1 的 DataGrid。 You also not have access to your source collection (List) from Window2 to modify it from there.
您也无法从 Window2 访问您的源集合(列表)以从那里修改它。
In that facts, you got 2 ways:在那个事实中,你有两种方法:
First of all and in any way I strongly recommend you to add some ID
field to your Student
object to be able unify each student.首先,无论如何我强烈建议您向您的
Student
object 添加一些ID
字段,以便能够统一每个学生。
If use external database
, you can simply call something like "UPDATE students s SET s.name = @name, s.age = @age... WHERE s.ID = @id"
from your Window2
when Save
button clicked.如果使用
external database
,您可以在单击Save
按钮时从Window2
中简单地调用类似"UPDATE students s SET s.name = @name, s.age = @age... WHERE s.ID = @id"
的内容。 @name, @age...
is new modified values @name, @age...
是新的修改值
If use public fixed collection
, you can access it from any part of your program.如果使用
public fixed collection
,您可以从程序的任何部分访问它。 When Window2
Save button clicked, you can search for student in it by student's ID and simply edit him.点击
Window2
Save 按钮后,您可以通过学生 ID 在其中搜索学生并简单地编辑他。 After Window2
closing you need just refresh DataGrid view by resetting ItemsSource. Window2
关闭后,您只需通过重置 ItemsSource 来刷新 DataGrid 视图。 It may look like this:它可能看起来像这样:
Student class:学生 class:
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}";
}
}
Fixed and public collection class to store Students:固定和公共集合 class 存储学生:
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}";
// }
}
}
Update button click handler at Window1:在 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();
}
}
And some kind of Window2:还有某种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();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.