Hallo Alf, hallo th69,
zunächst einmal vielen Dank für eure Hilfestellung. Ich dachte canExecute kann nur true oder false sein. Diese Annahme war also falsch. CanExecute kann also true, false und Null sein.
Grundsätzliche habe ich verstanden wie das MVVM pattern funktioniert und auch die Vorteile, die es einem eröffnet.
Wo ich bis jetzt noch Schwierigkeiten habe ist einzuordnen wo nun welcher Programmcode hingehört und was einzelne Programmteile bewirken.
Wie das Binding zwischen View und ViewModel funktioniert habe ich verstanden.
Nachfolgend nochmal der vollständige Programmcode indem ihr meine Fragen jeweils im Programmcode findet:
<Grid>
<Button x:Name="btn_speichern" Content="Datensatz speichern" HorizontalAlignment="Left" Margin="25,350,0,0" VerticalAlignment="Top" Height="48" Width="150" />
<DataGrid x:Name="DataGrid1" Margin="25,100,25,100" AlternatingRowBackground="Aqua" AutoGenerateColumns="false" VerticalGridLinesBrush="#FFF8F4F4" HorizontalGridLinesBrush="#FFFAF7F7">
<DataGrid.Columns>
<DataGridTextColumn Header = "Vorname" Binding ="{Binding Vorname}" Width="100" />
<DataGridTextColumn Header = "Nachname" Binding ="{Binding Nachname}" Width="100" />
<DataGridTextColumn Header = "Geburtsort" Binding ="{Binding Geburtsort}" Width="*" />
</DataGrid.Columns>
</DataGrid>
<TextBox x:Name="txtMitarbeiternr" HorizontalAlignment="Left" Height="22" Margin="150,65,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="133" />
<Label Content="Mitarbeiternr" HorizontalAlignment="Left" Height="30" Margin="25,60,0,0" VerticalAlignment="Top" Width="100" FontSize="16" FontWeight="Bold"/>
<Button x:Name="Btn_OK" Content="OK" HorizontalAlignment="Left" Margin="325,65,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.1,-0.564" Width="124" />
</Grid>
internal class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Deine Verson mit new (); ist erst ab Sprachversion C#9 oder höher verfügbar
// Ich nutze die Community Version Visual Studio 2022; keine ausstehenden Updates; ist die Sprachversion bei mir verfügbar?
public ObservableCollection<MitarbeiterViewModel> AllMitarbeiter { get; } = new ObservableCollection<MitarbeiterViewModel>();
string firstname;
string lastname;
string geburtsort;
public DelegateCommand LoadCommand { get; set; }
public MainViewModel()
{
//Button wurde gedrückt DelegateCommand wird ausgeführt; Warum muss ein neues Object vm erzeugt werden???
this.LoadCommand = new DelegateCommand((vm) => LoadData(vm));
}
private void LoadData(object boxedMainViewModel)
{
//Welche Daten soll das object boxedMainViewModel aufnehmen
var mainViewModel = boxedMainViewModel as MainViewModel;
mainViewModel.LoadAllMitarbeiter();
}
private void LoadAllMitarbeiter()
{
this.AllMitarbeiter.Clear();
foreach (var mitarbeiter in this.mitarbeiterService.GetAll())
{
this.AllMitarbeiter.Add(mitarbeiter);
}
}
//Den Part verstehe ich nicht, wozu dient der Mitarbeiterservice?
public MitarbeiterOverviewViewModel(MitarbeiterService mitarbeiterService)
{
this.mitarbeiterService = mitarbeiterService;
SqlConnection connection = new SqlConnection("Data Source=....;initial Catalog = Company_Test;Integrated Security=True");
connection.Open();
/// Wenn ich es richtig verstanden habe, benötige ich alles was hiernach kommt, sprich das try & catch nicht mehr.
/// Die Datenbankverbindung stelle ich zukünftig über die neue Klasse ADO.Net Entity Data Model her??? Aber warum brauche ich dann noch die
/// SQL connection???
try
{
string result_txt = txtMitarbeiternr.Text;
MessageBox.Show(result_txt);
int lfdNr = Convert.ToInt32(result_txt);
String[] Daten1 = new String[3];
String a = "";
String b = "";
String c = "";
ObservableCollection<Mitarbeiter> AllMitarbeiter = new ObservableCollection<Mitarbeiter>();
for (int lfdNr = 1; lfdNr <= 3; lfdNr++)
{
SqlCommand command = new SqlCommand("use Company_Test select * from Mitarbeiter Where [Mitarbeiternr] = " + (lfdNr), connection);
SqlDataReader reader = null;
reader = command.ExecuteReader();
reader.Read();
a += reader["Vorname"].ToString();
b += reader["Nachname"].ToString();
c += reader["Geburtsort"].ToString();
Daten1[0] = a;
Daten1[1] = b;
Daten1[2] = c;
Mitarbeiter newtemp = new Mitarbeiter(a, b, c);
a = "";
b = "";
c = "";
AllMitarbeiter.Add(newtemp);
}
DataGrid1.Items.Add(AllMitarbeiter[0]);
DataGrid1.Items.Add(AllMitarbeiter[1]);
DataGrid1.Items.Add(AllMitarbeiter[2]);
}
catch
{
MessageBox.Show("Es ist ein Fehler aufgetreten!");
}
}
public string Firstname
{
get => firstname;
set
{
if (firstname != value)
{
firstname = value;
this.RaisePropertyChanged();
}
}
}
... //
private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
if (!string.IsNullOrEmpty(propertyName))
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Mein MainWindow (Model) sieht zurzeit wie folgt aus:
namespace ....
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
Nach meinem derzeitigen Verständnis wird das Button-Click Event durch ein Command-Binding ersetzt. Dazu wird der OK-Button per Datenbindung mit dem ViewModel verbunden. Das ViewModel enthält die Logik, was mit dem View passieren soll wenn z.B. ein Button geklickt wird, eine Änderung etc. erfolgt.
Wird nun der OK-Button geklickt erzeugt es einen neuen DelegateCommand, dieser wiederum ruft die Methode LoadData auf usw..
Ich hoffe, dass es bis hierhin richtig verstanden und wiedergegeben habe. Ich glaube es wäre für mich sehr hilfreich wenn wir Schritt für Schritt vorgehen.
Ich habe die letzten Tage soviel gelesen, dass ich den Wald vor lauter Bäume nicht mehr sehe.
Gruß
Timm
Guten Abend Alf,
habe die letzten Tag versucht mein Vorhaben, mit deiner Hilfestellung, umzusetzen.
Die folgenden Klassen habe ich angelegt:
Dann habe ich noch
4. MainWindow (Model)
5. meine View (XAML)
Die Mitarbeiternr. wird nun in eine Textbox eingegeben und durch einen OK_Button erfolgt das Auslesen der Datensätze aus der Datenbank. Diese werden dann in der ObservableCollection abgelegt. Aktuell noch mit dem Ereignis Button_click.
public class DelegateCommand : ICommand
{
readonly Action<object> execute;
readonly Predicate<object> canExecute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Predicate<object> canExecute, Action<object> execute) =>
(this.canExecute, this.execute) = (canExecute, execute);
public DelegateCommand(Action<object> execute) : this(null, execute) { }
public void RaiseCanExecuteChanged() => this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
public bool CanExecute(object parameter) => this.canExecute?.Invoke(parameter) ?? true;
public void Execute(object parameter) => this.execute?.Invoke(parameter);
}
Beim DelegateCommand ist mir nicht klar warum als parameter "null" übermittelt wird. Nach meinem Verständnis kann ein Button doch nur geklickt also True oder nicht geklickt False liefern.
Des Weiteren weiß ich nicht wie ich den Konstruktor des DelegateCommand füllen muss, damit dieser dann das Auslesen aus der Datenbank durchführt.
Hier mein Ansatz:
internal class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string firstname;
string lastname;
string geburtsort;
public DelegateCommand Load_Data { get; set; }
public MainViewModel()
{
//Wie muss der Konstruktor gefüllt werden???
this.Load_data = new DelegateCommand();
}
public string Firstname
{
get => firstname;
set
{
if (firstname != value)
{
firstname = value;
this.RaisePropertyChanged();
}
}
}
.
.
.
private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
if (!string.IsNullOrEmpty(propertyName))
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Auch ist mir nicht ganz klar, wo der nachfolgende Programmcode hingehört:
private void Btn_GO_Click(object sender, RoutedEventArgs e)
{
SqlConnection connection = new SqlConnection("Data Source=TIMM\\TESTSQL;initial Catalog = Company_Test;Integrated Security=True");
connection.Open();
try
{
string result_txt = txtMitarbeiternr.Text;
MessageBox.Show(result_txt);
int lfdNr = Convert.ToInt32(result_txt);
String[] Daten1 = new String[3];
String a = "";
String b = "";
String c = "";
ObservableCollection<Mitarbeiter> AllMitarbeiter = new ObservableCollection<Mitarbeiter>();
for (int lfdNr = 1; lfdNr <= 3; lfdNr++)
{
//SqlCommand
a += reader["Vorname"].ToString();
b += reader["Nachname"].ToString();
c += reader["Geburtsort"].ToString();
Daten1[0] = a;
Daten1[1] = b;
Daten1[2] = c;
Mitarbeiter newtemp = new Mitarbeiter(a, b, c);
a = "";
b = "";
c = "";
AllMitarbeiter.Add(newtemp);
}
DataGrid1.Items.Add(AllMitarbeiter[0]);
DataGrid1.Items.Add(AllMitarbeiter[1]);
DataGrid1.Items.Add(AllMitarbeiter[2]);
}
catch
{
MessageBox.Show("Es ist ein Fehler aufgetreten!");
}
Habe mir anscheinend ein komplexes Thema ausgesucht, für meine ersten Gehversuche im Bereich MVVM Pattern.
Gruß
Timm
Hallo Alf,
ganz herzlichen Dank für deine ausführliche Hilfestellung. Versuche mich jetzt daran. Eine Rückmeldung erfolgt bzw. bin ich mir sicher, dass ich noch die eine oder andere Verständnisfrage haben werden.
Wünsche Dir einen schönen Feiertag.
Gruß
Timm
Hallo Alf,
danke für deine Hilfestellung. Das MVVM Pattern nutze ich bereits, um die Daten aus der Datenbank im DataGrid darzustellen. Das klappt auch soweit.
Nun dachte ich, dass ich zum Speichern Datatable/Dataset benötige.
Aber anscheinend geht es mit dem MVVM Pattern. Könntest du mir hier nochmal Hilfestellung geben?
Gruß
Timm
Guten Abend zusammen,
in einer WPF Anwendung versuche ich mich gerade am DataGrid. Dieses befülle ich aus einer MS SQL Datenbank, was auch gut funktioniert.
Nun möchte ich, dass Dateneingaben im DataGrid wiederum in die Datenbank gespeichert werden. Durch meine Recherche und lesen hier in den Forumsbeiträge bin ich auf einen Ansatz mit DataTable und DataSet gestoßen, jedoch im Bereich DataGridView (Windows Forms). Bin mir nicht sicher, ob es der richtige Ansatz ist.
Nachfolgend die entsprechenden Auszüge aus dem Programmcode:
public class Mitarbeiter
{
public string Vorname { get; set; }
public string Nachname { get; set; }
public string Geburtsort { get; set; }
public Mitarbeiter (string vorname, string nachname, string geburtsort)
{
Vorname = vorname;
Nachname = nachname;
Geburtsort = geburtsort;
}
}
private void Btn_GO_Click_1(object sender, RoutedEventArgs e)
{
try
{
.
.
.
String[] Daten1 = new String[3];
String a = "";
String b = "";
String c = "";
//Daten werden aus der Datenbank gelesen und zu einem Array hinzugefügt
a += reader["Vorname"].ToString();
b += reader["Nachname"].ToString();
c += reader["Geburtsort"].ToString();
Daten1[0] = a;
Daten1[1] = b;
Daten1[2] = c;
Mitarbeiter newtemp = new Mitarbeiter(a, b, c);
//Hier mein Ansatz mit DataTable und Dataset
DataTable table = new DataTable();
DataSet dataSet = new DataSet();
table.Columns.Add("Vorname", typeof(string));
table.Columns.Add("Nachname", typeof(string));
table.Columns.Add("Geburtsort", typeof (string));
//Datenzeile einfügen
DataRow dr = table.NewRow();
//Bin mir nicht sicher ob, der nachfolgende Programmcode so richtig ist???
dr[0] = newtemp;
.
.
.
}
catch
{
MessageBox.Show("Es ist ein Fehler aufgetreten!");
}
.
.
.
}
Wie füge ich die Daten nun aus dem Datatable in das DataGrid ein? Ich bin auf den nachfolgenden Ansatz gestoßen, der jedoch nicht funktioniert:
NameDesDataGrid.DataSource = table;
Zuvor habe ich die Daten aus dem Array immer per NamesDesDataGrid.Items.Add(newtemp); statisch eingefügt.
Wie kann ich mir des Weiteren anzeigen lassen, welche Daten im DataTable stehen bzw. wo werden diese im Bereich des Lokalfenster hinterlegt?
Gruß
Timm
Guten Abend M.L.,
vielen Dank für deine Hilfestellung und deine Mühe mit den Links. Hab es jetzt hinbekommen. Insbesondere der Hinweis, das meine Lösung im Bereich SQL zu suchen ist hat enorm geholfen. Genau, da lag der Hase im Pfeffer.
Gruß
Timm
Hallo,
bin neu hier im Forum und habe noch nicht viel Erfahrung in C#.
Ich möchte gerne auf einen bestimmten Datensatz (z.B. Zeile 1 und Spalte 2) in meiner Microsoft SQL Datenbank zugreifen.
Meine Datenbank ist wie folgt aufgebaut:
lfd.-Nr. | Vorname | Nachname |
1 | Max | Mustermann |
2 | Ute | Kaufmann |
3 | Peter | Scholz |
Meine C# Programm sieht wie folgt aus:
private void btn_start_Click(object sender, RoutedEventArgs e)
{
SqlConnection connection = new SqlConnection("Data Source=...;initial Catalog = test;Integrated Security=True");
try
{
connection.Open();
SqlCommand command = new SqlCommand("use test select * from Mitarbeiter", connection);
SqlDataReader? reader = null;
reader = command.ExecuteReader();
String s = "";
while (reader.Read())
{
s = s + reader["Vorname"].toString();
}
MessageBox.Show(s);
}
catch(Exception)
{
throw;
}
Das funktioniert auch soweit, aber ich erhalte in diesem Fall alle Name.
Wie lautet der Code wenn ich nur z.B. nur Max haben möchte (Google Suche erfolglos) ?
Auch die Suche auf Stake Overflow und in der Microsoft Dokumention https://learn.microsoft.com/de-de/sql/sql-server/?view=sql-server-ver16 geschaut aber anscheinend suche ich falsch 😃.
Wie sucht ihr nach solchen Dingen?
Vielen Dank vorab.
Gruß
Timm
Hallo,
Abt vielen Dank für deine ausführliche Rückmeldung und M.L. auch dir ein Dankeschön für dein Statement.
Habe mich nun für das Buch von Thomas Theis entschieden.
Gruß
Timm
Hallo zusammen,
bin neu hier im Forum und auf der Suche nach einem guten C# Buch.
Ich besitze fortgeschrittene Kenntnisse im Bereich VBA ( Visual Basic for Application) Programmierung und Grundkenntnisse in C# und Microsoft SQL Server.
Als nächstes Projekt habe ich mir vorgenommen eine C# Anwendung mit WPF sowie einer Microsoft SQL Datenbank zu erstellen.
Das Buch soll mich hierbei unterstützen.
Insbesondere blicke ich noch nicht bei folgenden Themen durch:
1.) spätere Ausführung des Programmes auf einem beliebigen PC und das damit einhergehende erstellen einer exe.Datei
2.) sicherer Verbindungsaufbau ,mit Password und Servername, zu der Microsoft SQL Datenbank; Sicherheitskonzepte sowie Schutz des erstellten Programmes
Meine Auswahl habe ich bereits auf die u.g. Bücher eingegrenzt:
C# - Codebook von Jürgen Bayer (Thread hier aus dem Forum)
Einstieg in C# mit Visual Studio 2022 von Thomas Theis (Thread hier aus dem Forum)
C# 8 mit Visual Studion 2019 von Andreas Kühnel
C# und .Net6 Grundlagen, Profiwissen und Rezepte von Jürgen Kotz und Christian Wenz
Schrödinger programmiert C# von Bernhard Wurm
Bin eher pragmatisch veranlagt und es wäre schon ein Buch zu haben, das mit Beispielen arbeiten und entsprechend gut erklärend geschrieben ist.
Ich denke, dass bestimmt das ein oder andere Buch bekannt ist und würde mich freuen wenn ich Hilfestellung bei der Auswahl bekäme.
Gruß
Timm