Laden...

Binding von MainWindow in Window1

Letzter Beitrag vor einem Jahr 16 Posts 771 Views
Binding von MainWindow in Window1

Hallo

Ich habe mal eine kleine frage.

Ich habe in MainWindow.xaml ein Label, ein Textbox und ein Button

    <Grid>
        <Label Content="{Binding FirstName}" HorizontalAlignment="Left" Margin="57,71,0,0" VerticalAlignment="Top"/>
        <TextBox HorizontalAlignment="Left" Margin="80,199,0,0" TextWrapping="Wrap" Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
        <Button Content="Button" Click="Button_Click" HorizontalAlignment="Left" Margin="389,155,0,0" VerticalAlignment="Top"/>

    </Grid>

In codebehind habe ich das drin.

    public partial class MainWindow : Window
    {
        MyClass viewModel = new MyClass();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = viewModel;

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
           Window1 test = new Window1();
            test.DataContext = viewModel;
            test.Show();
        }
    }

hier noch MyClass.cs

    public class MyClass : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged implementation

        public event PropertyChangedEventHandler PropertyChanged;

        protected void Notify(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion INotifyPropertyChanged implementation
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                if (value != _firstName)
                {
                    _firstName = value;
                    Notify("FirstName");
                }
            }
        }

        private string _firstName = "Naira";
    }

in mein Window1 habe ich nur eine Textbox.

Jetzt zu meiner Frage

Wenn ich aus MainWindow das Window1 öffne kann ich zwar in der Textbox die Werte ändern und in der MainWindow wird das Automatisch mit verändert das passt soweit.

Als nächstes möchte ich aber in Window1 im Codebehind direkt auf den String von FirstName zugreifen.

Wenn ich in Window1 in Codebehind die Zeile hinzufüge MyClass viewModel = new MyClass(); kann ich zwar mit viewModel.FirstName drauf zugreifen aber die Daten von MainWindow sind dann weg. Genauso wir es dann nicht Automatisch bei MainWindow umgeändert weil ich die Klasse dann ein Zweites mal eingebunden habe.

Wie kann man es lösen das die Verbindung der Klasse von MainWindow zu Window1 mit übernommen wird.

Kann mir bitte jemand ein Beispiel Code dafür geben.

Gruß

Mezzo

Lass es mich so erklären:

Du hast einen Korb und legst dort einen Apfel hinein. Wenn dein Bruder jetzt in diesen Korb hineinschaut, was sieht er? Genau, diesen einen Apfel.

Jetzt nimmt dein Bruder einen neuen Korb, der deinem Korb erstaunlich ähnlich ist, und schaut in diesen, was sieht er? Genau, gähnende Leere.

Wenn du erklären kannst, warum das so ist, dann hast du dein Problem erklärt.

Hat die Blume einen Knick, war der Schmetterling zu dick.

Hallo

Danke für deine Antwort.

Das habe ich schon verstanden, wenn ich MyClass in Window1 in Codebehind lade, das dieser dann leer ist.

Ist es überhaupt möglich das ich MyClass von MainWindow in Window1 auch in Codebehind übergeben kann? Nicht nur als Datacontent.

Nun ja du kannst casten

var viewmodel = DataContext as MyClass;

sowie weitere viele Dinge die aber alles Grundlagen von C# sind

wenn ich MyClass in Window1 in Codebehind lade, das dieser dann leer ist.

Hmmm, es ist auch hilfreich die richtige Terminologie zu verwenden. Wenn du eine neue Instanz erzeugst, dann wird diese eben nicht geladen, sondern erzeugt und ist auch nicht leer sondern enthält die default Werte.

Problematisch ist, das man dann oft aneinander vorbei redet weil man es falsch beschreibt/benennt.

Hat die Blume einen Knick, war der Schmetterling zu dick.

Hallo mezzo80,

daher solltest du deine VM-Klasse auch besser benennen, z.B. MainViewModel.

Außerdem wird bei MVVM statt den Ereignismethoden (wie z.B. Button_Click) im Codebehind die ICommand-Schnittstelle im ViewModel benutzt (Stichworte: DelegateCommand oder RelayCommand). So brauchst du nicht von außerhalb auf die VM-Klasse zugreifen, sondern der gesamte UI-Logikcode befindet sich in dieser VM-Klasse.

Hallo Zusammen,

Ich versteh das mit dem Command so wenn man eine Abfrage oder eine andere Funktion mit den Click des Buttons machen will.

Das öffnen eines neues Window Fenster habe ich so verstanden das man diese durch das Click Funktion aufruft. oder liege ich da Falsch?

@BlonderHans

ich habe das mit der var viewmodel ausprobiert leider wird mit da null ausgegeben und nicht die Daten.

Das MessageBox ist jetzt nur für mich das ich sehe das die Daten auch übergeben werden. ist nicht die eigentliche Funktion.

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            var viewModel = DataContext as MyClass;
            string Text1 = viewModel.FirstName;
            MessageBox.Show(Text1);
        }
    }

Generell ist MVVM eher darauf ausgelegt, alles in einem Fenster anzuzeigen (d.h. z.B. durch Austausch des Content).
Eine Möglichkeit ist z.B. durch Verknüpfung von View mit ViewModel in einem DataTemplate, s. DataTemplate in einem ContentControl.

Ansonsten benutzt man für die Erzeugung von Views aus dem ViewModel heraus sogenannte Services, s. z.B. C# – WPF Open a new View from the ViewModel (am besten in Verbindung mittels Dependency Injection (DI)).

Und zu deiner 2. Frage:

Der DataContext wird in deinem Code ja erst nach dem Aufruf des Konstruktors gesetzt, daher kannst du diesen dort noch nicht abrufen, sondern erst in später aufgerufenen Methoden (z.B. in den Ereignissen ContentRendered oder IsVisibleChanged).

Alternativ kannst du dem Konstruktor eine Referenz als Parameter mitgeben.

Ja, das Timing spielt halt auch eine große Rolle. Darum solltest du auch mit dem Debugger arbeiten und hier z.B. prüfen, welcher Wert in DataContext steckt. Dann wäre dir auch aufgefallen, dass der zu dem Zeitpunkt ebenfalls null ist.

Wenn du mal beschreiben könntest was du wirklich vorhast - also mehr Details als "ich will Daten mitnehmen" - dann könnte man dir wirklich Beispiel-Code geben.

Hat die Blume einen Knick, war der Schmetterling zu dick.

Hallo

Danke für die Antwort, ich bin noch nicht soweit mit mein Code weil ich zuerst die Funktionen Lernen will.

Mein Vorhaben ist dies, Ich will ein DataGrid die mit ein DataSet verbunden ist.

in dem 2. Window möchte ich ein Formular machen, zum Hinzufügen von Daten.

ein nächstes Formular zum Ändern.

Dies möchte ich auf für das TreeView genauso haben.

Da werden von mir noch mehrere Fragen kommen. Ich habe mir gedacht ich lerne es am besten wenn ich ein Projekt starte.

in diesen Projekt habe ich, Ribbon, AvalonDock, DataGrid, TreeView, Controls, mehrere Window, SQLite und dann noch dazu in CSV Datei Exportieren, als PDF Datei und Drucken.

Ich denke bis morgen Abend kann ich euch ein Code von mein Projekt geben.

Gruß

Mezzo

Zitat von mezzo80

Als nächstes möchte ich aber in Window1 im Codebehind direkt auf den String von FirstName zugreifen.

Hallo mezzo80

Da liegt schon der Fehler. Mit MVVM wird das anders gelöst. Was genau hast du vor?

Gruss
Alf

Hallo und allen noch ein gesundes neues Jahr.

Ich war leider Krank sorry für meine Späte Antwort.

Mir geht es hauptsächlich darum, wenn ein neues Window gestartet wird, wie man die Klassen mit übergibt.

Hier jetzt mal ein kleines Beispiel mit DataGrid und DataSet.

MainWindow XAML

<Window x:Class="Binding.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:Binding" d:DataContext="{d:DesignInstance Type=local:DataSetViewModel}"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ToolBar Grid.Row="0" >
            <Button x:Name="B_Neu" Content="Neu" Click="B_Neu_Click"/>
        </ToolBar>

        <DataGrid x:Name="DataGrid1" Grid.Row="1" ItemsSource="{Binding Familie}"/>

        <StatusBar Grid.Row="2" />
    </Grid>
</Window>

MainWindow C#

using System.Windows;


namespace Binding
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        
        DataSetViewModel viewModelData = new DataSetViewModel();
        public MainWindow()
        {
            
            InitializeComponent();

            this.DataContext = viewModelData;

            //Beispiel Daten zum Test
            viewModelData.DataSetNew("Hans", "Mustermann", "Diesestraße 4", "12345", "Musterort");
 
            DataGrid1.ItemsSource = viewModelData.Familie;
        }

        private void B_Neu_Click(object sender, RoutedEventArgs e)
        {
            var window = new Window1
            {
                DataContext = viewModelData.MyDataSet
            };
            window.Show();
        }
    }
}

DataSetViewModel.cs

namespace Binding
{
    internal class DataSetViewModel
    {
        public DataSet1 MyDataSet = new DataSet1();

        public DataSet1.FamilieDataTable Familie = new DataSet1.FamilieDataTable();

        
        public void DataSetNew(string Vorname, string Nachnache, string Strasse, string PLZ, string Ort)
        {
           Familie.Rows.Add("", Vorname, Nachnache, Strasse, PLZ, Ort);
           
        }
    }
}

Window1 XAML

<Window x:Class="Binding.Window1"
        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:Binding"
        mc:Ignorable="d"
        Title="Window1" Height="222" Width="371">
    <Grid>
        <Label Content="Vorname:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
        <Label Content="Nachname:" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top"/>
        <Label Content="Strasse:" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top"/>
        <Label Content="PLZ:" HorizontalAlignment="Left" Margin="10,103,0,0" VerticalAlignment="Top"/>
        <Label Content="Ort:" HorizontalAlignment="Left" Margin="185,107,0,0" VerticalAlignment="Top"/>
        <TextBox HorizontalAlignment="Left" Margin="120,18,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="230"/>
        <TextBox HorizontalAlignment="Left" Margin="120,49,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="230"/>
        <TextBox HorizontalAlignment="Left" Margin="120,80,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="230"/>
        <TextBox HorizontalAlignment="Left" Margin="120,111,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="54"/>
        <TextBox HorizontalAlignment="Left" Margin="230,111,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
        <Button Content="Speichern" HorizontalAlignment="Center" Margin="0,162,0,0" VerticalAlignment="Top" Width="95"/>

    </Grid>
</Window>

Window1 C#

using System.Windows;

namespace Binding
{
    /// <summary>
    /// Interaktionslogik für Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        
        public Window1()
        {
            InitializeComponent();
        }
    }
}

Ich habe noch eine DataSet1.xsd wo meine Tabelle drin ist.

Ich möchte nun das in Window1 in die Textboxen diese DataSet die ich in MainWindow habe gleich sind.

So das ich in Window1 in Codebehind auf das viewModelData.DataSetNew zugreifen kann. ohne das es in Window1 neu erstellt werden muss.

Gruß

Mezzo

Du solltest auch für Window1 nicht im Codebehind die Logik implementieren, sondern genauso wie für das MainWindow per Data Binding (d.h. im ViewModel) auf die Daten zugreifen.

Üblicherweise wird auch für jedes Window (und Page,Frame, ...) ein eigenes ViewModel erstellt (und die benötigten Daten dann vorher erstellt/kopiert).

Hast du dir schon [Artikel] MVVM und DataBinding durchgelesen?
Beachte besonders auch die Implementierung von INotifyPropertyChanged in jedem ViewModel sowie die generelle Benutzung von Eigenschaften für das Data Binding.

Hallo

Als erstes mal ein großes Dankeschön an Th69 der mir das sehr gut erklärt hat.

Anbei sende ich euch nun die Lösung.

MainWindow.xaml

<Window x:Class="DataGrid_mit_DataSet.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:DataGrid_mit_DataSet"
        mc:Ignorable="d"
        Title="DataGrid aus DataSet auslesen" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />

            <RowDefinition Height="14*" />
        </Grid.RowDefinitions>

        <ToolBar VerticalAlignment="Top" Grid.RowSpan="3">
            <Button x:Name="B_Neu" Content="Neu" Click="B_Neu_Click"/>
            <Button x:Name="B_Bearbeiten" Content="Bearbeiten" Click="B_Bearbeiten_Click" />
            <Separator />
            <TextBox x:Name="txt_Suchen" Width="250" />
            <ComboBox x:Name="Combo_SuchSpalte" Width="150" SelectedIndex="0">
                <ComboBoxItem Content="Alles" />
                <ComboBoxItem Content="Vorname" />
                <ComboBoxItem Content="Nachname" />
                <ComboBoxItem Content="Strasse" />
                <ComboBoxItem Content="PLZ" />
                <ComboBoxItem Content="Ort" />
                <ComboBoxItem Content="Telefon" />
                <ComboBoxItem Content="EMail" />
            </ComboBox>
            <Button x:Name="B_Suchen" Content="Suchen" Click="B_Suchen_Click" />
        </ToolBar>

        <DataGrid Grid.Row="2" x:Name="DataGrid1" ItemsSource="{Binding ViewKontakte}" />


    </Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;
using static DataGrid_mit_DataSet.DataGridFunktion;

namespace DataGrid_mit_DataSet
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // ViewModel mit die Funktionen werden eingebunden für MainWindow
        DataGridFunktion MyDataSet = new DataGridFunktion();
        // auch das ViewModel für Formular XAML wird hier mit eingebunden um die Daten zum ändern zu übergeben
        FormularViewModel MyFormularViewModel = new FormularViewModel();
        
        public MainWindow()
        {
            InitializeComponent();

            // BeispielDateien zum Anschauen werden eingefügt
            MyDataSet.DataSetNeu("Hans", "Müller", "Weitestrasse 4", "45678", "Weithausen", "03548 / 5687", "HansM@email.com");
            MyDataSet.DataSetNeu("Alex", "Mair", "Mautstrasse 8", "78439", "Mauten", "07568 / 3769", "MairA@email.com");
            MyDataSet.DataSetNeu("Fritz", "Neumaier", "Neuestrasse 12", "69753", "Neudorf", "09348 / 6974", "fritz@neumaier.de");

            // Hier wird das DataContext für MainWindow eingefügt um die Inhalte der Variabeln Anzeigen zu lassen.
            this.DataContext = MyDataSet;
        }

        private void B_Neu_Click(object sender, RoutedEventArgs e)
        {
            // Hier wird das Formular Fenster eingebunden
            var MyFormular = new Formular();

            // Besser ist es das Formular Fenster als Dialog zu öffnen. Da dann das MainWindow deaktiviert ist.
            // durch die IF Abfrage wird geprüft ob der Button in Formularfenster ausgeführt wurde.
            // um somit die Daten in DataGrid zu speichern.
            if (MyFormular.ShowDialog() == true)
            {
                // Dies ist die Funktion zum einfügen der Daten in DataGrid diese wurde in DataGridFunktion erstellt.
                MyDataSet.DataSetNeu(MyFormular.Vorname, MyFormular.Nachname, MyFormular.Strasse, MyFormular.PLZ, MyFormular.Ort, MyFormular.Telefon, MyFormular.EMail);
            }
        }

        private void B_Bearbeiten_Click(object sender, RoutedEventArgs e)
        {
            // Hier wird das Formular Fenster eingebunden
            var MyFormular = new Formular();

            // hier wird abgerufen welche Zeile in DataGrid Markiert wurde und wird dann in MyRow gespeichert
            var MyRow = DataGrid1.SelectedItem as System.Data.DataRowView;
            // in MyItem werden dann die Inhalte der Zeilen gespeichert.
            var MyItem = MyRow.Row as DataGridDataSet.KontakteRow;

            // Hier werden die Daten an das Formular fenster übertragen.
            MyFormularViewModel.Vorname = MyItem.Vorname;
            MyFormularViewModel.Nachname = MyItem.Nachname;
            MyFormularViewModel.Strasse = MyItem.Strasse;
            MyFormularViewModel.PLZ = MyItem.PLZ;
            MyFormularViewModel.Ort = MyItem.Ort;
            MyFormularViewModel.Telefon = MyItem.Telefon;
            MyFormularViewModel.EMail = MyItem.EMail;

            // Das DataContext für das Formular fenster wird zugeordnet damit die Daten auch Angezeigt werden.
            MyFormular.DataContext = MyFormularViewModel;

            // Besser ist es das Formular Fenster als Dialog zu öffnen. Da dann das MainWindow deaktiviert ist.
            // durch die IF Abfrage wird geprüft ob der Button in Formularfenster ausgeführt wurde.
            // um somit die Daten in DataGrid zu speichern.
            if (MyFormular.ShowDialog() == true)
            {
                // Hier werden die Änderungen in DataGrid übertragen diese Funktion ist auch wieder in DataGridFunktion definiert. 
                MyDataSet.DataSetBearbeiten(MyItem, MyFormularViewModel.Vorname, MyFormularViewModel.Nachname, MyFormularViewModel.Strasse, MyFormularViewModel.PLZ, MyFormularViewModel.Ort, MyFormularViewModel.Telefon, MyFormularViewModel.EMail);
            }
        }

        private void B_Suchen_Click(object sender, RoutedEventArgs e)
        {
            CBSpalte spalte = (CBSpalte)Combo_SuchSpalte.SelectedIndex;
            DataGrid1.ItemsSource = MyDataSet.DataGridSuchen(txt_Suchen.Text, spalte);
        }
    }
}

MainWindowViewModel.cs


namespace DataGrid_mit_DataSet
{
    internal class MainWindowViewModel : ViewModelBase
    {
        public DataGridDataSet MyDataGridDataSet = new DataGridDataSet();
        // bei diesen Beispiel ist das ViewModel für MainWindow sehr sehr klein da die Tabellen alle in ein DataSet erstellt sind.

        // Hier wird das DataSet eingebunden, somit sind dann alle Spalten der Tabelle verfügbar.
        // Hat ein DataSet mehrere Tabellen dann muss jede einzelne Tabelle so eingefügt werden.
        public DataGridDataSet.KontakteDataTable ViewKontakte {  get; set; } = new DataGridDataSet.KontakteDataTable();

    }
}

Als Bilddatei habe ich die DataGridDataSet.xsd abgebildet.

Ich muss 2 oder 3 Antworten erstellen da diese Meldung kommt. "Die Nachricht ist zu lang. Maximal erlaubte Zeichen: 8000"

DataGridFunktion.cs

using System.Data;


namespace DataGrid_mit_DataSet
{
    //Diese Klasse ist für die Funktionen zuständig
    internal class DataGridFunktion : MainWindowViewModel
    {
        // erstellen einen neuen Datensatz
        public void DataSetNeu(string Vorname, string Nachname, string Strasse, string PLZ, string Ort, string Telefon, string EMail)
        {
            ViewKontakte.Rows.Add("", Vorname, Nachname, Strasse, PLZ, Ort, Telefon, EMail);
        }

        // ändern ein Datensatz
        public void DataSetBearbeiten(DataGridDataSet.KontakteRow kontakteRow, string Vorname, string Nachname, string Strasse, string PLZ, string Ort, string Telefon, string EMail)
        {
            kontakteRow.Vorname = Vorname;
            kontakteRow.Nachname = Nachname;
            kontakteRow.Strasse = Strasse;
            kontakteRow.PLZ = PLZ;
            kontakteRow.Ort = Ort;
            kontakteRow.Telefon = Telefon;
            kontakteRow.EMail = EMail;
        }


        // Suchfunktion in DataGrid
        public DataGridDataSet.KontakteDataTable DataGridSuchen(string Suchtext, CBSpalte Spalte)

        {
            //Hier wird nochmal die Tabelle von DataSet eingebunden.
            DataGridDataSet.KontakteDataTable KontaktErgebnis = new DataGridDataSet.KontakteDataTable();

            //in dieser Variable werden die Suchergebnisse gespeichert
            string expression = "";

            // Hier wird abgefragt was in der ComboBox ausgewählt wurde
            // Wir fragen nur ab ob Alles ausgewäht wurde um alle Spalten zu durchsuchen.
            if (Spalte == CBSpalte.Alle)
            {
                //Bei dieser Schleife fangen wir mit 1 an, da in der Tabelle der erste eine ID ist die mit 0 anfängt
                //Die ID Spalte wollen wir nicht durchsuchen daher fangen wir mit i=1 an.
                //Ist die ID Spalte nicht vorhanden wird mit i=0 angefangen
                for (int i = 1; i < KontaktErgebnis.Columns.Count; i++)
                {
                    if (i > 1)
                        // dieses " OR " ist dafür weil wir alle Spalten durchsuchen
                        expression += " OR ";

                    //Hier wird die Spalten erstellt die wir haben.
                    string spalteErstellen = KontaktErgebnis.Columns[i].ColumnName;
                    //und in expression mit Spalten die ergebnisse eingetragen
                    //diese * ist dafür das Vor dem Eingabetext und nach den Eingabetext was anderes Stehen kann.
                    //wenn man aber genau das suchen will, was man Eingegeben hat müssen die zwei * raus.
                    expression += spalteErstellen + " LIKE '*" + Suchtext + "*'";
                }
            }
            // Wurde in der ComboBox eine genaue Spalte Ausgewählt dann geht es hier weiter
            else
            {
                //Hier wird das ergebnis von der Ausgewählten Spalte gesucht und gespeichert.
                expression = Spalte + " LIKE '*" + Suchtext + "*'";
            }

            //Nun muss es in DataGrid ja wieder zurück gegeben werden

            //Wir wird eine Zeile erstellt
            DataRow[] GefundeneDaten = ViewKontakte.Select(expression);

            //Wir ist eine Schleife wo unsere Gefunden Daten überprüft werden und Eingetragen werden.
            foreach (DataRow GefundeneData in GefundeneDaten)
            {
                KontaktErgebnis.Rows.Add(GefundeneData.ItemArray);
            }

            //Nun wird es wieder zurückgegeben.
            return KontaktErgebnis;
        }


        // Dies ist für die Ausgewählte Spalte
        // Wie die Namen sind ist nicht wichtig.
        // 0 ist der erste Item von der Combobox
        internal enum CBSpalte
        {
            Alle,           // Startet mit 0
            Vorname,        // 1
            Nachname,       // 2
            Strasse,        // 3
            PLZ,            // 4
            Ort,            // 5    
            Telefon,        // 6
            EMail           // 7
        }

    }
}

ViewModelBase.cs

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace DataGrid_mit_DataSet
{
    internal class ViewModelBase : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged implementation
        public event PropertyChangedEventHandler? PropertyChanged;

        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string? propertyName = null)
        {
            if (object.Equals(storage, value)) return false;
            storage = value;
            // Log.DebugFormat("{0}.{1} = {2}", this.GetType().Name, propertyName, storage);
            this.OnPropertyChanged(propertyName);
            return true;
        }

        protected void OnPropertyChanged([CallerMemberName] string? name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        #endregion INotifyPropertyChanged implementation
    }
}

Formular.xaml

<Window x:Class="DataGrid_mit_DataSet.Formular"
        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:DataGrid_mit_DataSet"
        mc:Ignorable="d"
        Title="Formular" Height="450" Width="400">
    
    <Grid>
        
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="2*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Label Grid.Column="0" Grid.Row="0" Content="Vorname:" FontSize="24" FontFamily="Arial Rounded MT Bold" />
        <TextBox Grid.Column="1" Grid.Row="0" x:Name="txt_Vorname" Text="{Binding Vorname}"/>

        <Label Grid.Column="0" Grid.Row="1" Content="Nachname:" FontSize="24" FontFamily="Arial Rounded MT Bold" />
        <TextBox Grid.Column="1" Grid.Row="1" x:Name="txt_Nachname" Text="{Binding Nachname}"/>

        <Label Grid.Column="0" Grid.Row="2" Content="Strasse:" FontSize="24" FontFamily="Arial Rounded MT Bold" />
        <TextBox Grid.Column="1" Grid.Row="2" x:Name="txt_Strasse" Text="{Binding Strasse}"/>

        <Label Grid.Column="0" Grid.Row="3" Content="PLZ:" FontSize="24" FontFamily="Arial Rounded MT Bold" />
        <TextBox Grid.Column="1" Grid.Row="3" x:Name="txt_PLZ" Text="{Binding PLZ}"/>

        <Label Grid.Column="0" Grid.Row="4" Content="Ort:" FontSize="24" FontFamily="Arial Rounded MT Bold" />
        <TextBox Grid.Column="1" Grid.Row="4" x:Name="txt_Ort" Text="{Binding Ort}"/>

        <Label Grid.Column="0" Grid.Row="5" Content="Telefon:" FontSize="24" FontFamily="Arial Rounded MT Bold" />
        <TextBox Grid.Column="1" Grid.Row="5" x:Name="txt_Telefon" Text="{Binding Telefon}"/>

        <Label Grid.Column="0" Grid.Row="6" Content="E-Mail:" FontSize="24" FontFamily="Arial Rounded MT Bold" />
        <TextBox Grid.Column="1" Grid.Row="6" x:Name="txt_EMail" Text="{Binding EMail}"/>

        <Button Grid.Column="0" Grid.Row="7" Content="Abbrechen" IsCancel="True" />
        <Button x:Name="b_Speichern" Grid.Column="1" Grid.Row="7" Content="Speichern" Click="b_Speichern_Click" />

    </Grid>
    
</Window>

Formular.xaml.cs

using System.Windows;

namespace DataGrid_mit_DataSet
{
    /// <summary>
    /// Interaktionslogik für Formular.xaml
    /// </summary>
    public partial class Formular : Window
    {

        // Diese Veriablen sind nur zum zurücksenden der Daten an das MainWindow
        public string Vorname => txt_Vorname.Text;
        public string Nachname => txt_Nachname.Text;
        public string Strasse => txt_Strasse.Text;
        public string PLZ => txt_PLZ.Text;
        public string Ort => txt_Ort.Text;
        public string Telefon => txt_Telefon.Text;
        public string EMail => txt_EMail.Text;

        public Formular()
        {
            InitializeComponent();
        }

        private void b_Speichern_Click(object sender, RoutedEventArgs e)
        {
            //Hier wird bestätigt das der Button Speichern gedruckt wurde und wird an das MainWindow zurückgegeben und das Formular wird geschlossen.
            this.DialogResult = true;
        }
    }
}

FormularViewModel.cs

namespace DataGrid_mit_DataSet
{
    // Dieses ViewModel erbt von ViewModelBase, das ViewModelBase ist für dafür das geändertete Daten auch Angezeigt werden.
    internal class FormularViewModel : ViewModelBase
    {
        private string _Vorname;

        public string Vorname
        {
            get => _Vorname;
            set => SetProperty(ref _Vorname, value);
        }

        private string _Nachname;

        public string Nachname
        { 
            get => _Nachname;
            set => SetProperty(ref _Nachname, value);
        }

        private string _Strasse;

        public string Strasse
        {
            get => _Strasse;
            set => SetProperty(ref _Strasse, value);
        }

        private string _PLZ;
        public string PLZ
        {
            get => _PLZ; 
            set => SetProperty(ref _PLZ, value);
        }

        private string _Ort;
        public string Ort
        {
            get => _Ort; 
            set => SetProperty(ref _Ort, value);
        }

        private string _Telefon;
        public string Telefon
        {
            get => _Telefon; 
            set => SetProperty(ref _Telefon, value);
        }

        private string _EMail;
        public string EMail
        {
            get => _EMail; 
            set => SetProperty(ref _EMail, value);
        }

    }
}

Ich hoffe ich habe alles und ich hoffe man kann es gut verstehen.

Ohne Th69 hätte ich das nicht so verstanden, Danke nochmals

Gruß

Mezzo

Nur als Info noch: es fehlt jetzt noch die Einbindung der Commands in die ViewModels (statt der Button_Click-Methoden im Codebehind), um vollständig MVVM-konform zu sein.