更改 TextBox 文本时自动更改 DataGrid 中的数据(Xml 源)
Posted
技术标签:
【中文标题】更改 TextBox 文本时自动更改 DataGrid 中的数据(Xml 源)【英文标题】:Automatically change data in DataGrid when I change TextBox Text (Xml source) 【发布时间】:2020-12-04 00:24:35 【问题描述】:我对编程很陌生,我正在使用 C# 和 WPF 创建一个小的客户管理应用程序。
在我的代码中,我使用DataGrid
来显示来自 XML 文件的数据。
我的问题是,当我更改特定单元格的TextBox
文本并且我考虑在TextBox
上使用TextChanged
事件时,我希望DataGrid
中的数据同时更改,但我想不通了解如何管理其余部分。
(代码并不完美,目前并非一切都运行良好)
代码隐藏:
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml;
namespace Kunden2
public partial class MainWindow : Window
List<Customer> customerlist = new List<Customer>();
public int RowNumber;
public MainWindow()
InitializeComponent();
if (TextBoxListe.Text.Length != 0)
ShowList(TextBoxListe.Text + ".xml");
RowCount();
//Button Refresh
private void ButtonRefresh_Click(object sender, RoutedEventArgs e)
ShowList(TextBoxListe.Text + ".xml");
//Button Add
private void ButtonAdd_Click(object sender, RoutedEventArgs e)
AddPerson();
//Button Save
private void ButtonSave_Click(object sender, RoutedEventArgs e)
SaveXML();
MessageBox.Show("Erfolgreich gespeichert.");
//Show List
private void ShowList(string list)
if (TextBoxListe.Text.Length != 0)
if (File.Exists(TextBoxListe.Text + ".xml"))
XmlSerializer serial = new XmlSerializer(typeof(List<Customer>));
using (FileStream stream = new FileStream(Environment.CurrentDirectory + "/" + list, FileMode.Open, FileAccess.Read))
customerlist = ((List<Customer>)serial.Deserialize(stream));
DataGrid.ItemsSource = customerlist;
else
MessageBox.Show("Datei existiert nicht!");
else
MessageBox.Show("Bitte eine Liste eingeben");
TextBoxNummer.Text = "";
//Selection to TextBox
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
object item = DataGrid.SelectedItem;
if (item == null)
TextBoxName.Text = "";
TextBoxLastName.Text = "";
TextBoxFirma.Text = "";
return;
string Nummer = (DataGrid.SelectedCells[0].Column.GetCellContent(item) as TextBlock).Text;
string Name = (DataGrid.SelectedCells[1].Column.GetCellContent(item) as TextBlock).Text;
string NachName = (DataGrid.SelectedCells[2].Column.GetCellContent(item) as TextBlock).Text;
string Firma = (DataGrid.SelectedCells[3].Column.GetCellContent(item) as TextBlock).Text;
TextBoxNummer.Text = Nummer;
TextBoxName.Text = Name;
TextBoxLastName.Text = NachName;
TextBoxFirma.Text = Firma;
//Add Person
private void AddPerson()
RowNumber++;
customerlist.Add(new Customer() NachName = TextBoxLastName.Text, Name = TextBoxName.Text, Firma = TextBoxFirma.Text, KundenNummer = RowNumber, Aktiv = true );
updateDataGrid();
TextBoxNummer.Text = "";
TextBoxName.Text = string.Empty;
TextBoxLastName.Text = string.Empty;
TextBoxFirma.Text = string.Empty;
//Update Data
private void updateDataGrid()
DataGrid.ItemsSource = null;
DataGrid.ItemsSource = customerlist;
//Save to XML
private void SaveXML()
if (TextBoxName.Text.Length == 0 && TextBoxLastName.Text.Length == 0 && TextBoxFirma.Text.Length == 0)
XmlSerializer serial = new XmlSerializer(typeof(List<Customer>));
using (FileStream stream = new FileStream(Environment.CurrentDirectory + "/" + TextBoxListe.Text + ".xml", FileMode.Create, FileAccess.Write))
serial.Serialize(stream, customerlist);
else
XmlSerializer serial = new XmlSerializer(typeof(List<Customer>));
using (FileStream stream = new FileStream(Environment.CurrentDirectory + "/" + TextBoxListe.Text + ".xml", FileMode.Create, FileAccess.Write))
serial.Serialize(stream, customerlist);
//Button Delete
private void ButtonLöschen_Click(object sender, RoutedEventArgs e)
XmlDocument xdoc = new XmlDocument();
FileStream up = new FileStream(TextBoxListe.Text + ".xml", FileMode.Open);
xdoc.Load(up);
XmlNodeList list = xdoc.GetElementsByTagName("Customer");
for (int i = 0; i < list.Count; i++)
XmlElement cu = (XmlElement)xdoc.GetElementsByTagName("Customer")[i];
if (cu.GetAttribute("KundenNummer") == TextBoxNummer.Text)
cu.SetAttribute("Aktiv", "false");
break;
up.Close();
xdoc.Save(TextBoxListe.Text + ".xml");
ShowList(TextBoxListe.Text + ".xml");
private void RowCount()
RowNumber = customerlist.Count();
//Button Open
private void ButtonOpen_Click(object sender, RoutedEventArgs e)
ShowList(TextBoxListe.Text + ".xml");
//Text Changed Event
private void TextBoxName_TextChanged(object sender, TextChangedEventArgs e)
// What to do here to update the "Name"?
XAML
<Window x:Class="Kunden2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Kunden2"
mc:Ignorable="d"
Title="Verwaltung" Height="500" Width="800" Background="Gray">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="ButtonAdd" Content="Hinzufügen" Grid.Row="3" Margin="16,28,30,47" Click="ButtonAdd_Click" Grid.Column="2"/>
<Button x:Name="ButtonSave" Content="Speichern" Grid.Row="3" Grid.Column="1" Margin="22,28,18,47" Click="ButtonSave_Click"/>
<Button x:Name="ButtonRefresh" Content="Neu Laden" Grid.Column="1" Grid.Row="2" Margin="22,46,18,29" Click="ButtonRefresh_Click"/>
<Button x:Name="ButtonDelete" Content="Löschen" Grid.Row="2" Grid.Column="2" Margin="10,46,30,29" Click="ButtonLöschen_Click"/>
<TextBox x:Name="TextBoxName" Grid.Row="1" Grid.Column="1" TextChanged="TextBoxName_TextChanged" Margin="52,27,48,63"/>
<TextBox x:Name="TextBoxLastName" Grid.Row="1" Grid.Column="2" Margin="50,27,50,63"/>
<TextBox x:Name="TextBoxFirma" Grid.Row="1" Grid.Column="1" Margin="52,90,48,0"/>
<TextBox x:Name="TextBoxNummer" Grid.Row="1" Grid.Column="2" Margin="50,90,50,0" IsReadOnly="True" />
<TextBlock Text="Vorname:" Grid.Row="1" Grid.Column="2" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="87,0,94,90"/>
<TextBlock Text="Name:" Grid.Row="1" Grid.Column="1" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="97,0,110,90" RenderTransformOrigin="0.479,0.03"/>
<TextBlock Text="Firma" Grid.Row="1" Grid.Column="1" FontSize="20" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,63,110,27"/>
<TextBlock Text="Nummer" Grid.Row="1" FontSize="20" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,63,94,27" Grid.Column="2"/>
<DataGrid x:Name="DataGrid" Grid.RowSpan="4" Grid.ColumnSpan="2" IsReadOnly="True" SelectionChanged="DataGrid_SelectionChanged" SelectionMode="Single" SelectionUnit="FullRow" AutoGenerateColumns="False" Margin="5,5,247,5" >
<DataGrid.Columns>
<DataGridTextColumn Header="Nr." Binding="Binding KundenNummer"/>
<DataGridTextColumn Header="Vorname" Binding="Binding Name"/>
<DataGridTextColumn Header="Name" Binding="Binding NachName"/>
<DataGridTextColumn Header="Firma" Binding="Binding Firma"/>
<DataGridTextColumn Header="Aktiv" Binding="Binding Aktiv"/>
</DataGrid.Columns>
</DataGrid>
<TextBox x:Name="TextBoxListe" Grid.Column="1" Margin="52,67,48,24"/>
<TextBlock Text="Liste:" Grid.Column="1" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="110,40,110,51"/>
<Button x:Name="ButtonOpen" Content="Öffnen" Grid.Column="2" Margin="16,52,30,24" Click="ButtonOpen_Click"/>
</Grid>
</Window>
客户类别
namespace Kunden2
public class Customer
[XmlAttribute]
public bool Aktiv get; set;
[XmlAttribute]
public int KundenNummer get; set;
[XmlElement]
public string Name get; set;
public string NachName get; set;
public string Firma get; set;
【问题讨论】:
【参考方案1】:由于您使用的是纯代码隐藏,我将向您展示一个解决方案,尽管我建议您熟悉 MVVM 设计模式,它可以让您免于通过绑定进行大量事件处理,并允许一个干净的表示与您的逻辑和数据分离。
要更新文本更改事件处理程序中的数据,您需要访问DataGrid
中的SelectedItem
,并将其对应属性设置为关联TextBox
的Text
。
private void TextBoxName_TextChanged(object sender, TextChangedEventArgs e)
if (DataGrid.SelectedItem is Customer customer)
customer.Name = ((TextBox)sender).Text;
但是,此更改尚未反映在用户界面中,因为您的 Customer
模型未实现 INotifyPropertyChanged
。您可以像下面那样为您的所有属性实现它。它的作用是在属性被修改时引发PropertyChanged
事件,以表明控件必须更新其绑定以获取更改的值。
public class Customer : INotifyPropertyChanged
private string _name;
public string Name
get => _name;
set
if (_name != value)
_name = value;
OnPropertyChanged();
// ...your other properties.
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
【讨论】:
谢谢您的遮阳篷。它对我来说效果很好。以上是关于更改 TextBox 文本时自动更改 DataGrid 中的数据(Xml 源)的主要内容,如果未能解决你的问题,请参考以下文章
如何在文本更改时启用/禁用绑定到 ICommand 的按钮,而不是失去 TextBox 的焦点
System.Windows.Forms.TextBox不会更改ref文本
如何在下拉列表更改时使用 jQuery 清除 TextBox