更改 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,并将其对应属性设置为关联TextBoxText

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 源)的主要内容,如果未能解决你的问题,请参考以下文章

TextBox更改选择文本

如何在文本更改时启用/禁用绑定到 ICommand 的按钮,而不是失去 TextBox 的焦点

System.Windows.Forms.TextBox不会更改ref文本

如何在下拉列表更改时使用 jQuery 清除 TextBox

UWP的TextBox和PasswordBox使用输入范围更改触摸键盘InputScope

文本框文本在WPF中更改了事件