Hallo ThaKilla
Du kannst ein DTO (data transfer object) verwenden um deine Daten zu serialisieren. Das ist einfach eine Klasse mit den entsprechenden Properties. Das DTO füllst du mit den Daten aus dem DataGridView/DataSet und serialisierst es dann. Wenn du mehrere Dateien haben willst, serialisierst du einfach mehrere DTOs. Ist wirklich einfach.
Gruss
Alf
Zitat von AmpelB
Ich sehe gerade, bei dir sind die Bilder als byte[] drin. Wie hast du das denn gemacht?
Bei deinem 2. Bild, habe ich Byte (WPF) ausgewählt, statt Icon (Windows Forms).
Habe mal update gemacht. Bei mir sieht es so aus. Beim einbinden von der Resource kannst du einen Typ auswählen.
Ist es eventuell einfach unter Images?
Zitat von visionmaster
Dann bleibt wohl wirklich nur der von Dir vorgeschlagene Weg. Ich werde es versuchen...
Dann kannst du dir auch mal AutoIt anschauen.
Zitat von bigeddie
ch hoffe ihr könnt mir etwas weiter helfen.
Wenn es nicht zwingend notwendig ist, dann arbeite nicht direkt mit Office.Interop. Siehe hier:
https://mycsharp.de/forum/posts/3842033
Zitat von Palladin007
Lieber mit Hilfe von DocumentFormat.OpenXml, oder - mein Favorit - Du nutzt das Framework ClosedXml, was das durchaus komplexe OpenXml-ObjektModel deutlich vereinfacht.
Gruss
Alf
Hallo Ralf2022
Ich vermute das TCPServerStopp
nicht aufgerufen wird. Setze doch mal einen Breakpoint und prüfe das. [Artikel] Debugger: Wie verwende ich den von Visual Studio?
Hast du den TCP/IP-Server asynchron gestartet?
Gruss
Alf
Zitat von CSharpNewbie2022
Zitat von Alf Ator
Du könntest ein Haupt-ViewModel benutzen, dass die anderen ViewModels hält und mit Daten füttert.
Ich habe dir mal ein minimales Beispiel angehängt.Ich hatte jetzt doch lust etwas wenig zu schlafen und mich daran zu setzen Dein Beispiel ist doch dahingegen anders als mein Fall, da ich mehrere Views habe, es ist ähnlich zu dem Fall bei dem Verlinkten anderen Beitrag.
Das Beispiel lässt sich doch supereinfach auf deinen Fall erweitern. Ich dachte das reicht aus.
Jetzt frage ich mich ok, Text zu Zahl aus der DB ist Teil des Models/Businessmodels, Laden des Inhalts der Zahlen aus einer Datei und Speichern in eine Datei auch auch?
Ja. Schau dir dazu das Repository-Pattern an.
Was passiert dann im ViewModel, werden dort nur die Klassen DB und File laden als Objekte erstellt und die Methoden genutzt + Button Commands und Alle Binding Variablen?
Ja.
Versuche ich soviel in Modell zu legen, wie geht?
Es geht darum, Geschäftslogic und UI(-Logic) voneinander zu trennen.
Die Methoden des Modells spucken als return values dann strings oder listen aus und diese werden im Viewmodell an die Binding variablen übergeben?
Ja.
Ich hab das Beispiel etwas erweiter.
Du könntest ein Haupt-ViewModel benutzen, dass die anderen ViewModels hält und mit Daten füttert.
Ich habe dir mal ein minimales Beispiel angehängt.
Okay, sorry für den unverständlichen Beitrag 😦
Der Name CellViewModel ist etwas ungünstig gewählt. Ich hatte mich an deinem Beispielcode orientiert.
RowViewModel wäre besser. Du kannst im RowViewModel' für jede Spalte, die im DataGrid angezeigt werden soll ein Property anlegen. Für 50 Spalten also 50 Properties.
Die Lösung passt eventuell nicht zu deinem UseCase. Was sollte denn mit den angezeigten Daten gemacht werden? Sollen die nur angezeigt, oder bearbeitet werden? Ändert sich das Excel-Dokument regelmässig, oder bleibt es gleich?
Hallo Caveman
Wie Abt schon gemeint hat, ObservableCollection nur einmal zuweisen und binden.
public ObservableCollection<Model> Items { get; } = new ObservableCollection<Model>();
Statt das Model im View zu verwenden könntest du auch ein ViewModel verwenden. Siehe Bild.
Edit:
Das wäre dann übrigens auch die Lösung für dein Problem mit List<List<T>>
<DataGrid.Columns> <DataGridTextColumn Header="Header" Binding="{Binding CellValue}" /> </DataGrid.Columns> <behav:Interaction.Triggers> <behav:EventTrigger EventName="AutoGeneratingColumn" SourceObject="{Binding ElementName=TestDataGrid}" > <behav:InvokeCommandAction Command="{Binding ColumnGeneratingEvent, Mode=OneWay}" PassEventArgsToCommand="True" /> </behav:EventTrigger> </behav:Interaction.Triggers>
Entweder Autogenerate Columns, oder Columns fest definieren. Beides gleichzeitig kommt nicht so gut.
Servus Caveman
Das sieht doch schonmal ganz gut aus. Von mir noch ein paar Anmerkungen.
ObservableCollection verwende ich eher im UI-Context. Wurde aber schon erwähnt. Die ObservableCollection kann dann im ViewModel gefüllt werden. Je nach Komplexität kann der User dann noch in ein UserViewModel konvertiert werden.
Erstellen und Anzeigen vom Window mache ich nicht im App-Konstruktor, sondern:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// hier
}
}
Du hast View und ViewModel als Singleton erstellt. Sofern es dafür keine speziellen Gründe gibt, würde ich die transient machen. ViewModel würde ich generell nicht als Singleton machen, sonst hast du auf einmal Daten auf der View, die da nicht sein sollten.
Gruss
Alf
Okay, ich verstehe das Problem.
Die Width von der ersten Column ist auf Auto gesetzt. Durch das aufklappen des Expanders wird die Column breiter.
Um das zu verhindern, kannst du die Column-Width fest auf 200 setzten.
Was mit dem Expander nicht geht, ist dass der Expander die Column 'verlässt'. Dafür müsstest du dann z.B. ein Popup verwenden.
Du könntest das gewünschte Verhalten evt. auch mit Grid.ColumnSpan="3" erreichen.
Gruss
Alf
Hallo CSharpNewbie2022
Stell doch den ZIndex vom Expander testweise mal auf 1.
Gruss
Alf
Edit:
Oder so:
<Rectangle Fill="LightGray" Width="200" Height="100" Grid.ZIndex="2" />
<Ellipse Fill="LightBlue" Width="100" Height="100" Grid.ZIndex="3"/>
<Expander HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="myExpander" Grid.ZIndex="4" ExpandDirection="Right">
Hatte dein Projekt mal aufgemacht um das anzuschauen und hab ganz, ganz grob sowas wie MVVM und Schichten reingemacht.
Les die Frage von BlonderHans nochmal genau. Zwischen 'TblProgramminfo' und 'TblScheibendaten' besteht keine (für uns erkennbare) Beziehung. Wie ist da die Verbindung?
Hallo Andi153
In der Doku steht, dass ServiceBase in der Assembly "System.ServiceProcess.ServiceController.dll" ist.
Gruss
Alf
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 ill_son
Bin mir nicht sicher ob ich den Aufbau richtig verstanden habe. Ich denke es fehlen noch Informationen um die Fragen zu beantworten.
Wo werden denn die Channel-Objekte (??) gehalten und wo werden sie erzeugt? Im Repository?
wer ist dann für den Aufruf von Dispose() zuständig? Ich würde jetzt sagen das Repository.
Dann ja.
Sollte der Channel dann ein Disposed-Event haben?
Nur wenn es benötigt wird.
Gruss
Alf
Du hast ja einen Link bezüglich eines Schichtmodels gepostet. Aber ist das nicht bereits das, was MVVM macht? Auf mich macht es den Eindruck, als wäre das so. Ich kann mich da aber auch irren.
Einfache Antwort: MVVM ist im Schichtenmodel im UI-Teil einzuordnen.
(Natürlich ist das Thema komplexer, aber das spar ich mir hier mal.)
Hallo StayCalm
Zitat von StayCalm
Die dritter GroupBox "Combine" hat einen Button und ein Label. Wenn man in der dritten GroupBox den Button „Combine“ klickt, soll im Label der String aus der Person-TextBox mit dem String des Animal-TextBox zusammengeführt werden.
Wenn es sich bei dem Zusammenführen von Text um komplexe Geschäftslogik handelt, dann sollte sich diese in der entsprechenden Schicht befinden:
https://mycsharp.de/forum/threads/111860/artikel-drei-schichten-architektur
Dein CombineViewModel bekommt dann ein ICommand-Property, dass vom MainViewModel aus gesetzt werden kann, und vom Button ausgelöst wird.
// So ähnlich könnte das aussehen. Habe es ohne Testen runtergeschrieben.
public MainViewModel(CombinationService combinationService)
{
this.combineViewModel = new CombineViewModel
{
CombineCommand = new RelayCommand<string>(() => this.CombinationResult = combinationService.Combine(this.personViewModel.Name, this.animalViewModel.type));
};
}
Gruss
Alf
Hallo JanBauer
CameraCaptureUI tut wohl nicht mit WinForms, man soll wohl MediaCapture verwenden:
https://learn.microsoft.com/en-us/uwp/api/windows.media.capture.mediacapture?view=winrt-22621
Da gibt es auch ein Beispiel.
Gruss
Alf
Hö? Was machst du? Du brauchst nur ein Grid. Und warum ist da immer noch md und sm?
Hallo Bronstein
Du hast die Breite so konfiguriert: md="4"; mach das mal weg.
Gruss
Alf
Hallo pollito
Es gibt fertige Komponenten zu kaufen, die das können.
Alternativ in Pdf oder Html konvertieren und anzeigen.
Gruss
Alf
Hallo joerg55
Das ist nicht ohne weiteres möglich.
Man kann zwar CheckedListBox überschreiben:
public class CheckedListBoxWithCustomHeight : CheckedListBox
{
private int itemHeight = 40;
[Browsable(true)]
[Category("Behavior")]
public override int ItemHeight { get => this.itemHeight; set => this.itemHeight = value; }
}
Aber die Schrift selbst wird nicht verschoben.
Schwer zu sagen, ohne den relevanten Code zu kennen.
Grundsätzlich werden die Daten ins ViewModel geladen und nicht direkt auf der View geändert. Das ViewModel hat ICommand-Properties, die an die Buttons in der View gebunden sind (https://www.c-sharpcorner.com/UploadFile/851045/command-design-pattern-in-C-Sharp/).
Wird der Command ausgelöst, wird eine Methode im ViewModel ausgeführt, die die Daten lädt. Mit CommunityToolkit.Mvvm wird die entsprechende Methode einfach mit [RelayCommand] attributiert. Das Command-Property wird generiert und nicht händisch implementiert.
Das ViewModel informiert dann die View über das INotifyPropertyChanged-Event. Mit CommunityToolkit wird das Property mit [ObservableProperty] attributiert, anstatt das NotifyPropertyChanged-Event händisch auszulösen.
Beispiel:
internal partial class MainViewModel : ObservableRecipient
{
[ObservableProperty]
private ObservableCollection<string>? data;
[RelayCommand]
void LoadData()
{
Data = new ObservableCollection<string>
{
"Data A",
"Data B",
"Data C"
};
}
}
<StackPanel>
<ListView ItemsSource="{Binding Data}" />
<Button Content="Load Data" Command="{Binding LoadDataCommand}" />
</StackPanel>
Benutzt du denn ein ViewModel pro Page oder eines für alle?
Möglicherweise der Virenscanner auf dem anderen Rechner.
Weil es hier noch keine Antwort gibt:
Wenn die Daten programatisch geändert werden, soll das nicht im DataGrid gemacht werden, sondern an dem gebunden Property. Das muss natürlich entsprechend mit INotifyPropertyChanged ausgestattet sein.
Hallo TomSchmitz
Ich glaube nicht dass es eine Library gibt, die das Verschmelzen automatisch macht.
Wirst also mit der passenden Library Header und Footer auslesen und neues Pdf generieren müssen.
Über die Forensuche findest du die Libraries, die du verwenden kannst.
Gruss
Alf
Hallo Timm
CanExecute kann also true, false und Null sein.
CanExecure ist eine Art Methode, die true oder false zurück gibt. Kann bei deiner ICommand-Implementierung aber auch null sein, dann wird also keine Methode übergeben und CanExecute gibt dann immer true zurück.
<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> ... <Button x:Name="Btn_OK" Content="OK" HorizontalAlignment="Left" Margin="325,65,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.1,-0.564" Width="124" />
Im Xaml-Code fehlen die Bindings. Beim Button das Command-Binding und beim DataGrid das ItemsSource-Binding.
// 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?
Die C#-Version hängt mit der .NET-Version zusammen, die im Projekt eingestellt ist.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version
//Button wurde gedrückt DelegateCommand wird ausgeführt; Warum muss ein neues Object vm erzeugt werden??? this.LoadCommand = new DelegateCommand((vm) => LoadData(vm));
'vm' ist in diesem Fall das ViewModel, dass vom Command (per CommandParameter-Binding) übergeben wird. Es wird also kein neues Objekt erzeugt.
Das beantwortet auch die Frage:
//Welche Daten soll das object boxedMainViewModel aufnehmen
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;
Der MitarbeiterService stellt die Verbindung zur Geschäftslogik her, von dort kommen die Mitarbeiter-Daten und da gehen sie wieder hin, wenn sie gespeichert werden sollen. Alles was mit Datenbank zu tun hat, wird dahinter versteckt und hat in der UI nichts mehr zu suchen.
Schau dir dafür das hier an: https://mycsharp.de/forum/threads/111860/artikel-drei-schichten-architektur
SqlConnection connection = new SqlConnection("Data Source=....;initial Catalog = Company_Test;Integrated Security=True"); connection.Open(); /// 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???
Kein Plan wo die Daten aktuell herkommen. Für die UI ist das auch nicht wichtig. Wie ich schon geschrieben hatte, muss der Datenbank-Kram aus der UI raus und hinter den MitarbeiterService.
Mein MainWindow (Model) sieht zurzeit wie folgt aus:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } }
Wo wird das ViewModel dem DataSource vom Window zugewiesen?
Nach meinem derzeitigen Verständnis wird das Button-Click Event durch ein Command-Binding ersetzt. check
Dazu wird der OK-Button per Datenbindung mit dem ViewModel verbunden. check
Das ViewModel enthält die Logik, was mit dem View passieren soll wenn z.B. ein Button geklickt wird, eine Änderung etc. erfolgt. checkWird nun der OK-Button geklickt erzeugt es einen neuen DelegateCommand, dieser wiederum ruft die Methode LoadData auf usw..
Der DelegateCommand wird schon im Konstuktor vom ViewModel erzeugt und enthält eine Verknüpfung auf die LoadData-Methode.
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.
Es wäre ja langweilig, wenn es einfach wäre. 😃
Hallo Timm
Das MainViewModel braucht noch ein Property für die Mitarbeiter-Liste:
public ObservableCollection<MitarbeiterViewModel> AllMitarbeiter { get; } = new();
Im View wird das DataGrid daran gebunden:
<DataGrid ItemsSource="{Binding AllMitarbeiter}" />
Ausserdem wird der Load-Button an den DelegateCommand gebunden:
<Button Content="Load Mitarbeiter" Command="{Binding LoadCommand}" CommandParameter="{Binding}" />
Der CommandParameter ist der DataContext, also das MainViewModel.
Des Weiteren weiß ich nicht wie ich den Konstruktor des DelegateCommand füllen muss, damit dieser dann das Auslesen aus der Datenbank durchführt.
Der execute-Parameter beim DelegateCommand ist die Methode, die beim Button-Click ausgeführt wird.
public MainViewModel()
{
// Load_data → LoadCommand
this.LoadCommand = new DelegateCommand((vm) => LoadData(vm));
}
...
private void LoadData(object boxedMainViewModel)
{
var mainViewModel = boxedMainViewModel as MainViewModel;
mainViewModel.LoadAllMitarbeiter();
}
...
private void LoadAllMitarbeiter()
{
this.AllMitarbeiter.Clear();
foreach (var mitarbeiter in this.mitarbeiterService.GetAll())
{
this.AllMitarbeiter.Add(mitarbeiter);
}
}
In this.mitarbeiterService.GetAll()
werden die Daten aus der Datenbank geladen.
Zum Testen reicht da auch sowas:
internal IEnumerable<Mitarbeiter> GetAll()
{
yield return new Mitarbeiter("Guybrush", "Threepwood", "Monkey Island");
yield return new Mitarbeiter("Elaine", "Marley", "Melee Island");
}
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.
Der canExecute-Parameter zeigt nicht an, ob der Button gedrückt wurde, sondern ob er gedrückt werden darf. Wenn nein, dann wird er in der UI deaktiviert angezeigt. Den kannst du erstmal ignorieren.
Auch ist mir nicht ganz klar, wo der nachfolgende Programmcode hingehört:
SqlConnection connection = new SqlConnection("Data Source=TIMM\\TESTSQL;initial Catalog = Company_Test;Integrated Security=True");
connection.Open();
In den MitarbeiterService, bzw. noch besser in das MitarbeiterRepository, dass vom MitarbeiterService benutzt wird (https://dotnettutorials.net/lesson/repository-design-pattern-csharp/).
Der Rest kann weg.
Habe mir anscheinend ein komplexes Thema ausgesucht, für meine ersten Gehversuche im Bereich MVVM Pattern.
Ja, der Einstieg ist nicht ganz einfach. Die Mühe lohnt sich aber, zum einen für stabilere Programme, zum anderen entwickelt es das eigene Programmier-Verständnis ungemein.
Gruss
Alf
PS: Es folgt noch ein zweiter Beitrag mit ein paar Anmerkungen.
Ja, diese Anforderung wird mit MVVM quasi miterledigt.
Es gibt mehrere Möglichkeiten das zu machen. Hier mal ein ganz einfaches Beispiel:
<ListView ItemsSource="{Binding AllMitarbeiter}">
<ListView.ItemTemplate>
<DataTemplate DataType="local:Mitarbeiter">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Vorname}" Width="100" />
<TextBlock Text="{Binding Nachname}" Width="100" />
<TextBlock Text="{Binding Geburtsort}" Width="100" />
<Button Content="Details" Width="60" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Hallo CSharpNewbie2022
Wie du schon richtig erkannt hast, ist es wichtig, Daten und UI voneinander zu trennen. Bei WPF gibt es dafür das MVVM-Pattern.
https://mycsharp.de/forum/threads/118261/artikel-mvvm-und-databinding
Ausserdem empfehle ich dir noch diesen Artikel:
https://mycsharp.de/forum/threads/111860/artikel-drei-schichten-architektur
Gruss
Alf
Guten Morgen
Ich nehme mal an, dass auf Knopfdruck gespeichert werden soll.
Statt dem ClickEvent kannst du das Command-Pattern verwenden.
Dafür bindest du ein Command an dein ViewModel:
<Button Content="Mitarbeiter speichern" Command="{Binding SaveCommand}" CommandParameter="{Binding AllMitarbeiter}" />
public RelayCommand<ObservableCollection<MitarbeiterViewModel>> SaveCommand { get; private set; }
Im Konstruktor vom ViewModel kann der Command instantiiert werden:
public MitarbeiterOverviewViewModel(MitarbeiterService mitarbeiterService)
{
this.mitarbeiterService = mitarbeiterService;
SaveCommand = new RelayCommand<ObservableCollection<MitarbeiterViewModel>>(SaveAll, CanSaveAll);
}
Eine Implementierung für RelayCommand gibt es hier: https://www.c-sharpcorner.com/UploadFile/20c06b/icommand-and-relaycommand-in-wpf/
Die Methode SaveAll, die vom Command aufgerufen wird, bekommt als Parameter die Liste mit den Mitarbeitern.
private void SaveAll(ObservableCollection<MitarbeiterViewModel>? allMitarbeiterViewModel)
{
if (allMitarbeiterViewModel == null) return;
var allMitarbeiter = allMitarbeiterViewModel.Select(ToMitarbeiter);
mitarbeiterService.SaveAll(allMitarbeiter);
}
Beachte hier, dass ich in meinem Beispiel-Projekt nicht das Model Mitarbeiter direkt im UI verwende, sondern ein MitarbeiterViewModel. Beim Landen und Speichern wird jeweils übersetzt. (Beachte, dass deine ViewModels INotifyPropertyChanged implementieren.)
private Mitarbeiter ToMitarbeiter(MitarbeiterViewModel viewModel)
{
return new Mitarbeiter(viewModel.Vorname, viewModel.Nachname, viewModel.Geburtsort);
}
Der MitarbeiterService hält ein MitarbeiterRepository, über das die Kommunikation mit der Datenbank stattfindet.
Statt über den MitarbeiterService kann das MitarbeiterRepository auch direkt im ViewModel verwendet werden.
Wichtig ist, dass ab hier die UI von der Datenbank und Logik-Schicht getrennt ist: https://mycsharp.de/forum/threads/111860/artikel-drei-schichten-architektur
Den UI-Kram kannst du schonmal ausprobieren. Ziel ist, dass auf Knopfdruck SaveAll mit deinen Mitarbeitern aufgerufen wird. Meine Implementierung im MitarbeiterService:
internal void SaveAll(IEnumerable<Mitarbeiter> allMitarbeiter)
{
foreach (var mitarbeiter in allMitarbeiter)
Debug.WriteLine(mitarbeiter);
}
Wenn das funktioniert, kann das Repository implementiert werden. Bei konkreten Fragen meldest du dich wieder hier.
Gruss
Alf
Hallo Timm2023
Bei WPF benutzt du am besten das MVVM-Pattern:
https://mycsharp.de/forum/threads/118261/artikel-mvvm-und-databinding
DataSet und DataTable brauchst du gar nicht.
Für die Mitarbeiter aus der Datenbank machst du dir in dein ViewModel eine ObservableCollection:
public ObservableCollection<Mitarbeiter> AllMitarbeiter { get; set; }
Im View kannst du daran binden:
<DataGrid DockPanel.Dock="Top" ItemsSource="{Binding AllMitarbeiter}" />
Les dich ein und fang damit an. Damit solltest du soweit kommen, dass die Mitarbeiter angezeigt werden. Für das Speichern kommst du dann mit deinem neuen MVVM-Ansatz wieder.
Gruss
Alf
Mit einem DataTemplate. Hier ist das ganz gut erklärt: https://wpf-tutorial.com/listview-control/listview-data-binding-item-template/
Hallo holzhaus2022
MVVM und Datenbinding ist auf jeden Fall der elegantere Weg 😛
Wenn dich die Ladezeit stört, kannst du ja erstmal ein paar Daten laden und dann den Rest nachladen.
Es ist ausserdem fraglich ob jemand in einer Listbox zig-tausende Einträge haben will.
Unter dem Stichwort Paging findest du eventuell was passendes.
Gruss
Alf
Hallo perlfred
Die "Byte Order Mark" ist nicht Teil der Daten. Sie wird Dateien vorangestellt um die Byte-Reihenfolge im Dokument anzuzeigen. Siehe Wikipedia: https://de.wikipedia.org/wiki/Byte_Order_Mark
Das BOM wird also von File.ReadLines korrekterweise nicht mit zurückgegeben.
Gruss
Alf
PS:
Es wird UTF-8 nicht empfohle das BOM zu benutzen, kommt aber trotzdem vor:
https://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-with-bom/2223926#2223926)
Hallo leuveg
Ich schlage vor, dass du die Gelegenheit nutzt und dich gleich noch in ein paar Themen einarbeitest:
Implementiere die Logik unabhängig von der UI:
https://mycsharp.de/forum/threads/111860/artikel-drei-schichten-architektur
Welche UI du dann verwendest, kannst du dann entscheiden. Versuchs doch mal mit WPF und MVVM:
https://mycsharp.de/forum/threads/118261/artikel-mvvm-und-databinding
Die Logik könntest du Test Driven implementieren:
https://www.c-sharpcorner.com/article/test-driven-development-in-c-sharp-net/
Um Pdf-Mergen kannst du eine Library wie https://www.pdfsharp.net/ verwenden.
SQLite ist okay. Die Datenbank-Abfragen sollten nicht direkt in der Logik stattfinde. Verwende dafür ein Pattern wie:
https://www.c-sharpcorner.com/article/factory-method-design-pattern/
oder ein ORM (Object-Relation-Mapper) wie: https://learn.microsoft.com/en-us/ef/.
Gruss
Alf
Die Fehlermeldung sagt etwas anderes. Dein Zertifikat ist nicht vertrauenswürdig. Da kann ich dir aber leider nicht weiterhelfen.
Hast du schonmal "Trusted_Connection= False" probiert?
Edit:
Kleine Tipp: Stell mal dein Visual Studio etc, auf Englisch um. Dann bekommst du englische Fehlermeldungen. Mit denen kann man unter Umständen mehr anfangen.
Zitat von Moma2023
Aktuelle Fehlermeldung: System.ArgumentException: "Keyword not supported: 'trustedconnection'."
Müsste das nicht "Trusted_Connection=True" sein?
Hallo Moma2023
Zitat von Moma2023
- und alle Datenbank-Tabelln enthalten sind
Hier etwas zum Lesen:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Ich weiss nicht, ob das auf diesen Fall passt, wollte aber eine Denkanregung geben.
Gruss
Alf
Dann musst du den Datenbanktyp natürlich auch zum Konvertieren verwenden:
Beispiel:
public class DateTimeConverter : ValueConverter<DateTime, MySqlConnector.MySqlDateTime>
{
public DateTimeConverter() : base(
dateTime => ConvertToDatabaseDateTime(dateTime),
mySqlDateTime => ConvertToApplicationDateTime(mySqlDateTime))
{ }
private static MySqlConnector.MySqlDateTime ConvertToDatabaseDateTime(DateTime dateTime)
{
return new MySqlConnector.MySqlDateTime(dateTime);
}
private static DateTime ConvertToApplicationDateTime(MySqlConnector.MySqlDateTime mySqlDateTime)
{
int year = mySqlDateTime.Year > 0 ? mySqlDateTime.Year : 1;
int month = mySqlDateTime.Month > 0 ? mySqlDateTime.Month : 1;
int day = mySqlDateTime.Day > 0 ? mySqlDateTime.Day : 1;
int hour = mySqlDateTime.Hour;
int minute = mySqlDateTime.Minute;
int second = mySqlDateTime.Second;
int millisecond = mySqlDateTime.Millisecond;
return new DateTime(year, month, day, hour, minute, second, millisecond);
}
}
Hallo pollito
private static DateTime ConvertToApplicationDateTime(DateTime dateTime)
{
if (dateTime == DateTime.MinValue)
{
// Handhabung für "0000-00-00 00:00:00" aus der Datenbank. Wir können hier z. B.
// DateTime.MinValue oder einen anderen Standardwert zurückgeben.
return DateTime.MinValue;
}
return dateTime;
}
DateTime.MinValue ist 01.01.0001 und nicht 00.00.0000.
Ausserdem sollte das Datum aus der Datenbank nicht vom Typ DateTime sein, sondern irgendwas mit DBDate oder so.
Gruss
Alf
Hallo Ralle77
Hier sind zwei Artikel, die du lesen und verstehen solltest. Damit lösen sich deine Probleme quasi von selbst.
https://mycsharp.de/forum/threads/118261/artikel-mvvm-und-databinding
https://mycsharp.de/forum/threads/111860/artikel-drei-schichten-architektur
Da das etwas aufwändig ist nochmal zu den konkreten Problemen für den Anfang:
Wie kann ich das realisieren, so das die Auswahlmöglichkeiten nicht fest sind, sondern sich der Tabelle anpassen ?
Entweder mittels DataBinding: https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/?view=netdesktop-7.0
Hier wie man das anwendet: https://www.c-sharpcorner.com/article/explain-combo-box-binding-in-mvvm-wpf/
Oder (so macht man das nicht):
<ComboBox x:Name="fahrzeugAuswahl" />
foreach (var fahrzeug in fahrzeuge)
{
this.fahrzeugAuswahl.Items.Add(fahrzeug.Name);
}
Gruss
Alf
Schau dir nochmal den Link an, den du gepostet hast:
https://learn.microsoft.com/de-de/dotnet/api/system.windows.input.key?view=windowsdesktop-7.0
Namespace:
System.Windows.Input
Assembly:
WindowsBase.dll
Du machst bei deinem Projekt eine Referenz auf die Assembly und machst bei deiner Klasse ein using auf den Namespace.
Ist die Referenz auf die WindowsBase eingetragen?
Ich hab mal ein bisschen rumprobiert:
<Style TargetType="iconPacks:PackIconMaterial">
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding Path=IsChecked,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToggleButton}}}">
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
<DataTrigger Value="False" Binding="{Binding Path=IsChecked,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToggleButton}}}">
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
<iconPacks:
PackIconMaterial
Kind="Glasses"
Foreground="{StaticResource yellow}"
Width="20"/>
Da wird doch die Farbe für das Icon gesetzt. Folglich müsstest du die Foreground-Eigenschaft für PackIconMaterial anpassen.
Vielleicht könntest du bei deinem ToggleButton-Style einen Trigger einbauen, der den Foreground für das PackIcon anpasst, wenn der Foreground vom ToggleButton gesetzt wird. Nur eine Idee, bin grade nicht sonderlich tief drin, in dem Thema.