Laden...
G
gagagurge
myCSharp.de - Member
2
Themen
5
Beiträge
Letzte Aktivität
vor einem Monat
Dabei seit
30.01.2015
Herkunft
Österreich
Erstellt vor einem Monat

UPDATE:

Ich habe das Problem gefunden, bin aber ins nächste kleine Problem gelaufen.

In diesem DataGrid benutze ich eigene Styles, wo auch das Event "PreviewMouseLeftButtonDown" auslöse. Weil ich dort eine Methode ausführe die mir mit LinksKlick eine Zeile selektiert und mit erneutem Linksklick auf die gleiche Zeile die Auswahl wieder aufhebt. Ich habe es versucht zu umgehen indem ich nach der Spalte frage wo meine Buttons liegen, damit da nichts passiert, aber leider sobald der Handler fertig ist, wird auch der Command Teil übersprungen. Habe auch veruscht als Click Event auszulösen, aber PreviewMouseLeftButtonDown gewinnt immer und alle anderen Ereignisse scheinen unberührt zu bleiben. Der Klick auf einen Button in der Spalte "Aktionen" markiert mir jetzt nicht mehr die Zeile aber der Button bleibt unberührt.

public void DoSelectedRow(object sender, MouseButtonEventArgs e)
{
   DataGridCell? cell = sender as DataGridCell;
   if (cell != null && !cell.IsEditing)
   {
       // Überprüfe, ob die Zelle aus der "Aktionen"-Spalte stammt
       if (cell.Column.Header != null && cell.Column.Header.ToString() == "Aktionen")
       {
           // Verhindere die Auswahl der Zeile
           e.Handled = true;
           return;
       }
       DataGridRow? row = FindVisualParent<DataGridRow>(cell);
       if (row != null)
       {
           row.IsSelected = !row.IsSelected;
           e.Handled = true;
       }
   }
}

public static Parent? FindVisualParent<Parent>(DependencyObject child) where Parent : DependencyObject
{
   DependencyObject parentObject = child;
   while (!((parentObject is System.Windows.Media.Visual)
           || (parentObject is System.Windows.Media.Media3D.Visual3D)))
   {
       if (parentObject is Parent || parentObject == null)
       {
           return parentObject as Parent;
       }
       else
       {
           parentObject = ((FrameworkContentElement)parentObject).Parent;
       }
   }
   parentObject = VisualTreeHelper.GetParent(parentObject);
   if (parentObject is Parent || parentObject == null)
   {
       return parentObject as Parent;
   }
   else
   {
       return FindVisualParent<Parent>(parentObject);
   }
}

Ich möchte den User nicht dazu zwingen mit STRG+Klick auf die Zeile die Auswahl aufzuheben, also hab ich unschön ein event "PreviewMouseRightButtonDown" eingebunden, dass mir die Auswahl der Zeile aufhebt. Es ist scheinbar die einzige Möglichkeit, weil LeftButtonDown zu mächtig ist 😃

Hab ausßerdem Plan C, KundeItemViewModl durchgeführt. Das hat dann letztendlich funktioniert mit dem binden und ich kann jetzt bearbeiten.

Falls jemand eine schönere/bessere/effektivere Variante hat, bitte gerne 😃
Cool wäre es "unselect Row" mit klick auf einer freien Fläche, aber ich habe nichts "brauchbares" googlen können.

Erstellt vor einem Monat

Hallo zusammen,

nachdem Google und Copilot nicht mehr weiter helfen können, hoffe ich hier auf Antworten.

Es handelt sich um eine WPF Anwendung für ein Nagelstudio mit dem DesignPattern MVVM.

SORRY jetzt schon, falls die Vorgeschichte so lang ist, aber ich denke es ist wichtig zu verstehen was da wo aufgerufen wird.

Ich habe ein MainWindow, dazu das MainWindowViewModel. Im MainWindow habe ich im oberen und im linken Bereich Buttons zum Navigieren von Views welche ich im rechten Bereich anzeige:

<!-- Ansicht -->
<Grid Grid.Row="1">
   <Grid.Resources>
       <DataTemplate DataType="{x:Type viewmodels:KundenViewModel}">
           <views:KundenView></views:KundenView>
       </DataTemplate>
       <DataTemplate DataType="{x:Type viewmodels:KundeAddEditViewModel}">
           <views:KundeAddEditView></views:KundeAddEditView>
       </DataTemplate>
   </Grid.Resources>
   <ContentControl Content="{Binding CurrentView}">
   </ContentControl>
</Grid>

Das ganze funktioniert auch inzwischen 😃

Im KundenView habe ich ein DataGrid wo ich alle Kunden anzeige.

ItemsSource="{Binding KundenItems}" SelectedItem="{Binding SharedService.SelectedKundeStore.SelectedKunde}"

Wenn KundenView aufgerufen wird:

public partial class KundenView : UserControl
{
   public KundenView()
   {
       InitializeComponent();
       this.Loaded += KundenView_Loaded;
   }
   private void KundenView_Loaded(object sender, RoutedEventArgs e)
   {
       System.Diagnostics.Debug.WriteLine($"DataContext: {this.DataContext}");
   }
}

Ist der DataContext= KundenViewModel
Das ist auch korrekt und es werden auch alle Kunden angezeigt.

Über einen Button "Neuer Kunde" im MainWindow kann ich einen neuen Kunden erstellen. Dazu wird die View "KundeAddEditView" im "CurrentView" angezeigt. Das funktioniert auch, mit einem Klick auf den Button "Speichern" in der KundeAddEditView wird der neue Kunde auch in die DatenBank gespeichert und mein CurrentView wechselt zurück zur KundenView wo ich alle Kunden sehe inklusive den neu erstellten. Alles Gut alles Top. Testweise habe ich eine 2. Command, die zwar das gleiche macht, aber einen SelectedKunde mitübernimmt. Wenn ich also einen Kunden aus der DataGrid selektiere und ich auf "Neuer Kunde" klicke, wird wieder die gleiche View "KundeAddEditView", mit all den Werten des selektierten Kunden, angezeigt. Passt auch, alles super bis jetzt.

Aber nun zum Problem:

Mein DataGrid mit den Kunden hat auch noch eine Spalte mit 2 Buttons: Bearbeiten, Löschen.

<Button Style="{StaticResource gridEditButton}" 
       Command="{Binding DataContext.NavigateKundeEditCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" 
       CommandParameter="{Binding}">
   <Icon:PackIconMaterial Kind="PencilOutline" Style="{StaticResource gridButtonIcon}"/>
</Button>

Ich wollte wie in meinem Test oben wieder die KundeAddEditView aufrufen und den Kunden bearbeiten. Leider wird das Command einfach nicht ausgelöst.

Ich habe auch das probiert:

<Button Style="{StaticResource gridEditButton}" 
       Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl},Mode=FindAncestor},Path=DataContext.NavigateKundeEditCommand}"
       CommandParameter="{Binding}">
   <Icon:PackIconMaterial Kind="PencilOutline" Style="{StaticResource gridButtonIcon}"/>
</Button>

und das:

<Button Style="{StaticResource gridEditButton}" 
       Command="{Binding ElementName=_Root, Path=DataContext.NavigateKundeEditCommand}"
       CommandParameter="{Binding}">
   <Icon:PackIconMaterial Kind="PencilOutline" Style="{StaticResource gridButtonIcon}"/>
</Button>

KundeView, was ja ein UserControl ist, habe ich auch noch das im UserControl Header meiner KundenView.xaml eingefügt

<UserControl
.
.
.
d:DataContext="{d:DesignInstance Type=ViewModels:KundenViewModel}"
x:Name="_Root"
>

Wollte versuchen ob ich das Command über den ElementName auslösen kann. Leider auch nichts.

Und das habe ich natürlich auch versucht:

<Button Style="{StaticResource gridEditButton}" 
       Command="{Binding NavigateKundeEditCommand}"
       CommandParameter="{Binding}">
   <Icon:PackIconMaterial Kind="PencilOutline" Style="{StaticResource gridButtonIcon}"/>
</Button>

Der letzte Versuch hat mir zumindest BindingFehler ausgegeben. Die Eigenschaft "NavigateKundeEditCommand" wurde im Objekt vom Typ "Kunde" (meine Model-Klasse) nicht gefunden.

Und ich denke da liegt der Hund begraben. Das Binding vom Command zeigt mir glaub ich nicht auf mein KundenViewModel (wo ja mein NavigateKundeEditCommand ist). 
Ich verstehe es nicht was ich falsch mache. Da die 3 oberen Command-Binding Versuche keine BindingFehler haben und ich jetzt auch nicht der Ober C#/VisualStudio Profi bin weiß ich auch nicht genau wo diese Versuche hin "gebindet" haben oder bzw ich da detailierter debuggen könnte.

Es gäbe theoretisch noch einen Plan B und einen Plan C:

Plan B: einen zentralen Button zum Bearbeiten, dann sollte theoretisch das Binding wie mit der DataGrid funktionieren. Sieht aber nicht so Stylisch aus 😉

Plan C: die einzelnen Kunden in der DataGrid in ein "KundenListeItemViewModel" zu verpacken und dort mein Command zu feuern. Aber dann müsste ich viel im Code umbasteln und ich hab ein bisschen Angst es dann zu "verschlimmbessern" und alles kaputt zu machen 😃

Ich hoffe das Problem detailiert genug beschrieben zu haben und freue mich über JEDE Hilfe! 
Vielleicht hat ja der ein oder andere ein ähnliches oder vielleicht sogar das gleiche Problem gehabt.

Vielen herzlichen Dank schon mal im Voraus!

Erstellt vor 9 Jahren

Um dich mit LINQ-Abfragen zu beschäftigen würd eich dir das openbook vom ehemaligen Verlag GalileoComputing (mittlerwiel Rehinwekr Computing) empfehlen.
Um deine LINQ-Filter dynamisch zu generieren finde ich den Artikel
>
gut.

Danke für den Tipp, Galileo Bücher sind immer TOP!

Naja zum Beispiel kannst du deinen Code ja mit Visual Studio kompilieren. Da brauchst du keinen extra Code schreiben.
Von VS gibt es die Express-Version, die wenn ich mich nicht irre kostenlos ist.

Ich benutze ja VS2013 ... Habe ich wohl offensichtlich nicht erwähnt. Sorry..

Erstellt vor 9 Jahren

Danke aber für die schnelle Antwort!!

Schau doch mal nach LINQ to SQL und Dynamic LINQ ExpressionBuilder

Ok ich versuche es mal so, danke! Falls dir dazu ein Tipp/Beispiel für meinen Konkreten Fall einfällt, immer her damit 😃

Also du willst dein Tool kompilieren verstehe ich das richtig?
Wieso holst du dir zum kompilieren nicht einen Compiler?

Ja ich möchte mein Tool kompilieren, es lässt sich ja auch kompilieren nur eben der Teil mit den Befehlen nicht..
Wie meinst du das mir einen Compiler holen?

Wenn du Fehlermeldungen hast, kopiere sie, wie du es hier getan, füge sie in google ein und schon wird dir eine mögliche Ursache der Probleme genannt 😉
Beispiel:
>

Naja, das habe ich ja auch gemacht, und das hat mir für vorherige Fehler ja auch geholfen, aber dieses Beispiel ist ja nicht wirklich hilfreich für mich 😃

Erstellt vor 9 Jahren

Hallo zusammen,

da ich jetzt einige Tage damit verbracht habe eine "passende" Lösung zu finden, habe ich mich, in der Hoffnung Hilfe zu bekommen, hier angemeldet .

Ich habe noch nicht die "Mega Erfahrungen" oder schreibe superschönen sauberen Code, aber Übung macht den Meister 🙂 Auch meine Ausdrucksweise ist vielleicht beim 1. mal Lesen auch nicht super toll verständlich, aber ich bemühe mich wirklich 🙂

Zum eigentlichen Thema:

Der Titel ist vielleicht nicht gerade optimal aber ich wollte jetzt keinene Roman rein schreiben.
Ich habe angefangen eine KFZ Werkstätten WPF Applikation zu entwickeln. + MS SQL Datenbank.

Ursprünglich wollte ich das ganze wie in Java mit EJB aufziehen aber ehrlich gesagt ist mir das ganze in C# etwas zu kompliziert 🙁 --> Mit offenen Armen und dankend nehme ich hier JEDE Hilfe gerne entgegen!!
Also habe ich mich für eine Quick and Dirty Version mit sturren Strings die SQL Anweisungen enthalten entschieden.

Um das ganze etwas "dynamischer" zu machen hatte ich folgende Idee:
Ich schreibe eine Methode in meiner super Klasse meiner Datenhaltungsklassen(Auto, Kunde, Marke, Modell,...) die mir mittels Reflection alle Attribute ausgibt. Danach bastle ich mir dynamisch ein Select zusammen (auch über mehrere Tabllen bzw. Datenhaltungs-Klassen.

So, jetzt habe ich ein SqlDataReader Objekt das zb eine Zeile aber ca 50 Spalten enthält. (Habe die Header der Spalten dynamisch erstellt um beim Auslesen dynamisch differenzieren zu können)

Ich bastle mir aus diesem SqlDataReader-Objekt jetzt meine Strings mit den Ausführungen zusammen.

Tja, nur dummerweise sind in diesen Strings Anweisungen drinnen die speziell geladene/bereits vorhandene Objekte verändern wollen.

BSP:
Ich habe eine Klasse KundeDlg.xaml.cs die im Vordergrund ein WPF Fenster hat.
In dieser KundeDlg.xaml.cs Klasse habe ich eine List<Kundenautos> und eine List<Autoliste>.
Kundenautos und Autoliste sind jeweils Datenhaltungs-Klassen und bestehen nur aus einem Konstruktor + Attribute mit get und set.

Über ein anderes Fenster suche ich in der DB nach einem Kunden und wähle diesen aus.
Jetzt möchte ich diese 2 erwähnten Listen "befüllen" um alle Autos eines Kunden anzuzeigen und mit den Daten weiter zu arbeiten. Dazu habe ich mir eben diese "dynamisch erstellten Anweisungs-Strings" erstellt.
Ich befinde mich so gut wie durchgehend in der Klasse KundeDlg.xaml.cs die im Namespace "MyWerkstatt" und im Unterordner "GUI" ist. Meine Datenhaltungsklassen befinden sich auch in "MyWerkstatt.Datenhaltung". Und jetzt möchte ich eben hier in KundeDlg.xaml.cs diese erstellten Anweisungen ausführen.
--> Bisher klappt das ja auch ganz gut, im Sinne von: Die Anweisungen in den Strings stimmen, da ich sie unter "normaler" Anwendung ausführen kann.

zb:


Autoliste.Add(new Auto()); //Autoliste wird im Konstruktor von KundeDlg.xaml.cs erstellt
Kundenautos.Add(new Kundenautos()); //Kundenautos wird im Konstruktor von KundeDlg.xaml.cs erstellt
Autoliste[0].ID=1;
Autoliste[0].Baujahr=2000;
Autoliste[0].PS=200;
Autoliste[0].Kommentar= "asdfadsfasdfasdfadsf";
Autoliste[0].Pickerl=new DateTime(2015,1,28);
Autoliste[0].Marke.ID=1;
Autoliste[0].Marke.Name= "VW";

Kundenautos[0].ID=1;
Kundenautos[0].AutoID=1;

Der Teil wo ich auf die Schnauze fliege:


CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameters = new CompilerParameters();
            
parameters.GenerateInMemory = true;
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
parameters.ReferencedAssemblies.Add("System.Data.dll");

Dann bastle ich mir mit einem StringBuilder sb den auszuführenden String:


StringBuilder sb = new StringBuilder();
sb.AppendLine(@"using System;");
sb.AppendLine(@"using System.Windows.Forms;");
sb.AppendLine(@"using MyWerkstatt;"); // <-- Kennt er nicht
sb.AppendLine(@"using MyWerkstatt.GUI;"); // <-- Kennt er nicht
sb.AppendLine(@"using MyWerkstatt.Datenhaltung;"); // <-- Kennt er nicht
sb.AppendLine(@"using System.Collections.Generic;");
sb.AppendLine(@"using System.Text;");
sb.AppendLine(@"using System.Threading.Tasks; ");
sb.AppendLine(@"using System.Windows; ");
sb.AppendLine(@"namespace MyWerkstatt"); // <-- Fehler
sb.AppendLine(@"{");
sb.AppendLine(@"public class Test{");
sb.AppendLine(@"public Test(){"); //habe im Netz gelesen man sollte mal versuchen einen Konstr anzulegen und dort die Objekte zu erstellen
sb.AppendLine(@"KundeDlg dlg ;"); // <-- Er kennt KundeDlg nicht.
sb.AppendLine(@"List<Kundenautos> Kundenautos ;"); // <-- Auch meine Datenhaltungsklassen nicht
sb.AppendLine(@"List<Auto> Autoliste ;");
sb.AppendLine(@"dlg = new KundeDlg();");
sb.AppendLine(@"Kundenautos = dlg.Kundenautos;");
sb.AppendLine(@"Autoliste = dlg.Autoliste;}");
sb.AppendLine(@"public void Funktion(){");
foreach(String s in befehle)
{
     sb.AppendLine(s); //hier sind die Befehle wie oben beschrieben, nur halt in Strings verpackt :)
}
sb.AppendLine(@"}}}"); // Schließe Methode, Class und Namespace

Zum Schluss noch das "ausführen":

CompilerResults result = provider.CompileAssemblyFromSource(parameters, sb.ToString());

Ähm, ja, hier ist das result schön mit Errors bepackt.
Meist: Compiler Error CS0234 und Compiler Error CS0246

Was mache ich falsch? und noch wichtiger: Könnt ihr mir einigermaßen folgen? 🙂

Wenn einer meint: Hey, löse doch das ganze mit Entities --> GERNE !!! nur wie?? 🙁
Oder: Gib mal mehr Infos! --> Gerne, nur welche? 🙂

Oder: Das ist absoluter Schrott! --> Ok, zeig mir bitte wie ich es besser Lösen kann.

Sorry für diesen Roman, nur ich denke mir, je besser ich mein Problem schildere, desto besser kann mir geholfen werden...

Danke schon mal fürs Lesen und ich freue mich über konstruktive und brauchbare Antworten 🙂
MFG gagagurge