Ok, ja.
Die IT hat sich heute morgen schon offenbart, es wird eine weiter ADirectory geben, dann kann das so weiterlaufen wie bisher.
Hallo Abt, danke für die Info. Aber Prizipiell wird das in die Richtung mit dem Webservice gehen? Ich meine, ist da die Berechtigungseinschränkung weniger restriktiv?
Beim Webservice brauche ich ja definitiv immer zwei Seiten, den Client und den Server. Die Terminals wären die Clients .... das heißt dann ich bräuchte noch eine Serverfunktionalität mit ASP oder dergleichen .... korrekt? Über Commands muss ich dann etwas beim Server antriggern ...
Da fällt mir ein, so etwas könnte man dann auch per MQTT oder OPC-UA steuern, wobei MQTT ja keine Datein versendet ...
Hallo zusammen, manche werden schon die Stirn runzeln, wenn sie schon die Überschrift lesen.
Aber der Reihe nach, ich fasse mal zusammen. In unserer Firma (gehört zu einem Konzern), sind alle Mitarbeiter-PC' in der Domäne eingegliedert, habe somit Berechtigung auf unsrere Server, je nachdem was für die User konfiguriert ist.
Jetzt haben wir auch noch Windows-Terminals, die sind nicht in der Domäne (oder jedenfalls nicht der angemeldete User), somit haben diese Terminals nun auf bestimmte Netzwerkbereiche keinen Zugriff. Diese Terminals sind für die Auftragswerfassung nötig. Dafür habe ich auch eine Applikation geschrieben, die aus dieser Auftragssoftware heraus angesprochen werden kann. Es wird eine ausführbare "EXE-Datei" mit Übergabeparameter gestartet, damit werden einmal gewisse Dinge in SAP geprüft, zum anderen werden aber auch PDF-Dateien zum Auftrag geprüft, und wenn diese vorhanden sind werden diese angezeigt.
Und hier ist jetzt mein Problem. Diese Netzwerkressource auf der diese PDF's abgelegt werden, wurde vor einer Woche ersetzt, weil diese nicht mehr den aktuellen Richtinien entsprochen hat, somit sind jetzt auch die Rechte "futsch".
Nun muss ich mir überlegen wie man das allgemein für diese Terminals wieder zum Rennen bekommt. Es soll auch eine kostengünstige uns ressourcenschonende Möglichkeit sein (Geräte sind noch gut), eventuell dann auch für spätere Transfers zu verwenden.
Folgende dinge habe ich schon angedacht, aber ich bin in der Abwägung was das beste, schnellste, einfachsteist zuweit weg weil ich die Erfahrung damit nciht habe. Hier mal Punkte, was ich mir gedacht habe:
Gibt es einen WebService oder kann man das relativ leicht selber machen, mit dem ich Dateien aus einem Verzeichnis erfassen und lesen kann, ohne dass der angemeldete User von dem Terminal Zugriff auf den Netzwerkbereich hat (Netzlaufwerk) ?? Gibt es da schon fertige DLL's die ich in C# verwenden kann? Eventuell wäre das auch eine Lösung für Maschinen die noch mit einem alten Betriebssystem arbeiten, um Dateien auszutauschen ??
Impersonation, ich weiss nicht ob das aus der Anwendung heraus funktionieren kann, wenn man für die Auswertung der PDF-Dateien und das anzeigen der PDF's im Code einen anderen user vorschaltet, der in der Konzerndomäne bekannt ist ??
Eine ausführbare Datei oder Batch mit den Argumenten die notwendig sind aufrufen. Die Batch müßte dann auch mit einem User arbeiten, welcher der Konzernsomäne bekannt ist. Wäre so etwas möglich?
Sonstige Ideen von euch ??
Ihr seht, ich bin mir sehr unschlüssig was ich genau machen soll oder was allgemein die beste oder alltagstaugliche Lösung wäre.
Bin jetzt echt etwas am Boden, denn diese bisherige Lösung hatte ich vor zwei Jahren mit diesen Kollegen erstellt, und jetzt das ...
Ja, du hast recht. Das veranschaulicht das ganze erst so richtig. Das hatte ich mir vor 4 Tagen auch gedacht, als ich nochmals dran ging. Ich danke dir / euch für eure sehr Gute Hilfe. Eventuell kommeich nochmal auf euch zurück, während meinem Projekt.
AAAAAhhhhhh, jetzt hab ichs geschnallt. In den zusammengestückelten Daten vom feld "Anschnittscheibe" waren total andere SapNummern drin wie da überhaupt eingetragen werden dürfen.
Trage ich die richtigen ein, dann klappt das ganze🙈🙈
Hallo, ich vermute jetzt dass der Zusammenhang der Datentabellen nicht richtig nachvollzogen werden kann, oder ich versteh es nicht, aber ich versuche den Zusammenhang nochmal zu erklären.
Ich fang erst mal so an. Es gibt im Datengemenge zwei Tabellen, die müssen zu einer gemeinsamen Tabelle gestrickt werden. Das sind folgende zwei Tabellen (aus denen wird ein "Hauptansichtstabelle" ==> WerkzeugProgramminfo-Tabelle generiert. Der Bezug zueinander, damit die Daten zusammenfinden können und was genau zusammen passt, ist die Spalte "SapMaterial", jede der beiden Tabelle besitzt diese Spalte (fungiert genaugenommen als Schlüssel).
Hier dann nochmal die Struktur der beiden Tabellen, die zu einer gemeinsamen Tabelle zusammengefügt werden (wie ich das mache dieht man ja im Code, denke das wird hier auch nicht ausschlaggebend sein):
//// Tabellenstruktur "Programminfo" erstellen
TblProgramminfo = new DataTable("Programminfo");
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "SapMaterial", DataType = typeof(string) });
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "Anschnittscheibe", DataType = typeof(string) });
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "RohlingErstellt", DataType = typeof(Boolean) });
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "PdfLaderErstellt", DataType = typeof(Boolean) });
//// Tabellenstruktur "Werkzeugdaten" erstellen
TblWerkzeugdaten = new DataTable("Werkzeugdaten");
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "ID", AutoIncrement = true, AutoIncrementSeed = 1, AutoIncrementStep = 1 });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "SapMaterial", DataType = typeof(string) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "Nenndurchmesser", DataType = typeof(Single) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "Schaftdurchmesser", DataType = typeof(Single) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "Schneidenlaenge", DataType = typeof(Single) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "HalsVorhanden", DataType = typeof(Boolean) });
Die fertige Tabelle mit den Daten sieht dann so aus, wie im Bild in WerkzeugProgramminfo-Tabelle_06.jpg
Diese Tabelle muss angezeigt werden, jetzt kommt das ABER:
Sie Spalte "Anschnittscheibe" muss als DataGridComboboxColumn gesetzt werden, denn sie soll aus der Scheibentabelle (das sind Schleifscheiben die ausgewählt werden können) die Schleifscheiben in den ComboBoxItems vorhalten, die ausgewählt werden können. Ich sage bewusst "ausgewählt werden können". Ist bei einem Datensatz der angezeigt wird, das Feld "Anschnittscheibe" nicht belegt (also leer), somit sieht der User das er hier noch eine SAP-Nummer zuweisen muss (siehe im Bild der Datensatz mit ID=8)
Habe ich das ganze nun besser erklärt, oder verstehe ich die Frage falsch?
Hallo, ich habe das Beispiel nun mal auf aufgebaut wie es bei mir dann in der Realität aussieht, natürlcih habe ich noch viel mehr Spalten, aber das sollte nachher nicht das Problem sein.
Ich denke das Problem liegt daran, dass ich aus zwei Tabellen eine Tabelle forme, welche die Daten der beiden Tabellen hält (soll ja die Hauptübersicht aus dem Datengemenge ein).
Sobald ich das mache, funktioniert die Bindung an das Feld "Anschnittscheibe" nicht mehr, die ComboBox-Items sind immer noch da.
Kann mir jemand sagen, an was es liegt? Muss ich an dem BindigExpression etwas ändern? Anbei noch der Code als ZIP (zuviele Zeichen!!) und ein Bild ...
Bin für jeden Tipp dankbar.
Code Behind (nur ein Ausschnitt), der Rest in der ZIP als Projekt:
/* ==============================================================================================================================*/
public MainWindow_03()
{
InitializeComponent();
//// Tabellenstruktur "Werkzeugdaten" erstellen
TblWerkzeugdaten = new DataTable("");
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "ID", AutoIncrement = true, AutoIncrementSeed = 1, AutoIncrementStep = 1 });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "SapMaterial", DataType = typeof(string) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "Nenndurchmesser", DataType = typeof(Single) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "Schaftdurchmesser", DataType = typeof(Single) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "Schneidenlaenge", DataType = typeof(Single) });
TblWerkzeugdaten.Columns.Add(new DataColumn() { ColumnName = "HalsVorhanden", DataType = typeof(Boolean) });
//// "Werkzeugdaten" Datensätze manuell zuweisen
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075777", 3.2, 3.5, 9, true });
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075777", 3.9, 3.6, 9, true });
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075777", 3.95, 3.7, 9, true });
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075777", 4.0, 3.5, 12.2, true });
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075777", 4.5, 3.9, 12.5, true });
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075777", 4.8, 3.95, 15.1, true });
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075999", 14.5, 13.9, 12.5, false });
TblWerkzeugdaten.Rows.Add(new object[] { null, "5075999", 14.8, 13.95, 15.1, true });
//// Tabellenstruktur "Programminfo" erstellen
TblProgramminfo = new DataTable("");
//tblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "ID", AutoIncrement = true, AutoIncrementSeed = 1, AutoIncrementStep = 1 });
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "SapMaterial", DataType = typeof(string) });
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "Anschnittscheibe", DataType = typeof(string) });
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "RohlingErstellt", DataType = typeof(Boolean) });
TblProgramminfo.Columns.Add(new DataColumn() { ColumnName = "PdfLaderErstellt", DataType = typeof(Boolean) });
//// Der Tabelle Programminfo ein Datensatz zuweisen
TblProgramminfo.Rows.Add(new object[] { "5075777", "7778888", false, true });
TblProgramminfo.Rows.Add(new object[] { "5075999", "8889999", false, true });
//// Gedamte Tabelle organisieren: Alle Spalten der Tabelle Programminfo in die Haupttabelle überführen
TblWerkzeugProgramminfo = TblWerkzeugdaten.Copy();
foreach(DataColumn dtCol in TblProgramminfo.Columns)
{
if (!TblWerkzeugProgramminfo.Columns.Contains(dtCol.ColumnName))
TblWerkzeugProgramminfo.Columns.Add(new DataColumn() { ColumnName = dtCol.ColumnName, DataType = dtCol.DataType});
}
//// Die Daten der beiden Tabellen "Werkzeugdaten" und "Programminfo" programmatisch zusammenführen (Tabelle "WerkzeugProgrammminfo" mit Daten bestücken)
foreach(DataRow rowWerkzeugProgramminfo in TblWerkzeugProgramminfo.Rows)
{
//// Über die SapMaterialspalte werden beide Tabellen abgeglichen
string sapMaterial = rowWerkzeugProgramminfo["SapMaterial"].ToString();
//// Datensatz aus der Tabelle "Programminfo" erfragen, ob es einen Datensatz mit der "SapMaterial" - Nummer gibt, wenn ja dann müssen diese Daten im aktuellen Datensatz eingefügt werden
DataRow rowProgramminfo = TblProgramminfo.AsEnumerable().Where(x => x["SapMaterial"].ToString().Trim() == sapMaterial).FirstOrDefault();
//// Über den Spaltennamen den Ableich der Daten durchführen
if (rowProgramminfo != null)
{
foreach (DataColumn dtColProgramminfo in TblProgramminfo.Columns)
rowWerkzeugProgramminfo[dtColProgramminfo.ColumnName] = rowProgramminfo[dtColProgramminfo.ColumnName];
}
}
//// Tabellenstruktur "Scheibentabelle" erstellen
TblScheibendaten = new DataTable("Scheibendaten");
TblScheibendaten.Columns.Add(new DataColumn() { ColumnName = "SAP-Nummer", DataType = typeof(string) });
TblScheibendaten.Columns.Add(new DataColumn() { ColumnName = "Abmessung", DataType = typeof(string) });
TblScheibendaten.Columns.Add(new DataColumn() { ColumnName = "Standard", DataType = typeof(string) });
TblScheibendaten.Columns.Add(new DataColumn() { ColumnName = "Anwendung", DataType = typeof(string) });
TblScheibendaten.Rows.Add(new object[] { "8318555", "250x16x76,2", "Schneid-Formend", "Anschnitt / Fuehren"});
TblScheibendaten.Rows.Add(new object[] { "8318556", "250x16x76,2", "Schneid-Formend", "Anschnitt / Fuehren" });
TblScheibendaten.Rows.Add(new object[] { "8318557", "250x16x76,2", "Schneid-Formend", "Anschnitt / Fuehren" });
//// Bringt hier nichts, dachte eventuell ...
//TblWerkzeugProgramminfo.AcceptChanges();
//// Gemeinsame Datentabelle "WErkzeugProgramminfo" dem DataGrid mit der DataGridComboBoxColumn anbinden
dg_Daten.ItemsSource = TblWerkzeugProgramminfo.AsDataView();
//// Zur Übersicht die gemeinsame Datentabelle noch in einem eigenen DataGrid anzeigen, zur Kontrolle der Vollständigkeit
dg_DatenOhneComboBox.ItemsSource = TblWerkzeugProgramminfo.AsDataView();
}
/* ==============================================================================================================================*/
private void dg_Daten_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if(e.Column.Header.ToString() == "Anschnittscheibe")
{
e.Column = new DataGridComboBoxColumn
{
Header = "Anschnittscheibe",
ItemsSource = TblScheibendaten.AsDataView(),
DisplayMemberPath = "SAP-Nummer",
//// ==> Lasse ich das frei, klappt die ITEMS-Bindung trotzdem
SelectedValuePath = "",
SelectedValueBinding = new Binding("Anschnittscheibe") { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged },
};
}
}
/* ==============================================================================================================================*/
}
}
Danke, BlonderHans, dein Beispiel funktioniert so. Dann habe ich das bei mir so vereinfacht über die SQL-Datentabellen die ich als Datenquelle habe aufgebaut, ohne die ID - Spalte bei der Automobil und Farbtabelle. Da hatte ich das Problem beim der DataGridColumBox mit dem SelectedValuePath = nameof( LackierungLookup.Id ), weil es diese ID-Spalte nicht gibt.
Habe dann DisplayMemberpath + SelectedValuePath einfach auf das gleiche Feld gerichtet, dann es es erst mal funktioniert ... habe unten den Code wie das aussieht ...
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private DataTable tblAutomobil;
private DataTable tblFarbe;
public MainWindow()
{
InitializeComponent();
//// Tabellenstruktur "Automobiltabelle" erstellen
tblAutomobil = new DataTable("Automobil");
tblAutomobil.Columns.Add(new DataColumn() { ColumnName = "ID", AutoIncrement = true, AutoIncrementSeed = 1, AutoIncrementStep = 1 });
tblAutomobil.Columns.Add(new DataColumn() { ColumnName = "Hersteller", DataType = typeof(string) });
tblAutomobil.Columns.Add(new DataColumn() { ColumnName = "Baujahr", DataType = typeof(string) });
tblAutomobil.Columns.Add(new DataColumn() { ColumnName = "Lackfarbe", DataType = typeof(string) });
tblAutomobil.Columns.Add(new DataColumn() { ColumnName = "Kilometerstand", DataType = typeof(string) });
//// "Automobiltabelle" Datensätze manuell zuweisen
tblAutomobil.Rows.Add(new object[] { null, "VW", "2015", "Blau", "50000" });
tblAutomobil.Rows.Add(new object[] { null, "BMW", "2012", "Grau", "100000" });
tblAutomobil.Rows.Add(new object[] { null, "BMW", "2019", "Schwarz", "30000" });
tblAutomobil.Rows.Add(new object[] { null, "Mercedes", "2018", "Weiss", "40000" });
tblAutomobil.Rows.Add(new object[] { null, "OPEL", "2020", "Silber", "50000" });
tblAutomobil.Rows.Add(new object[] { null, "VW", "2021", "", "50000" });
//// Tabellenstruktur "Farbtabelle" erstellen
tblFarbe = new DataTable("Farbe");
tblFarbe.Columns.Add(new DataColumn() { ColumnName = "Farbe", DataType = typeof(string) });
tblFarbe.Columns.Add(new DataColumn() { ColumnName = "Farbzusatz", DataType = typeof(string) });
tblFarbe.Columns.Add(new DataColumn() { ColumnName = "Pigmentierung", DataType = typeof(string) });
tblFarbe.Rows.Add(new object[] { "Blau", "Alkyd", "leicht" });
tblFarbe.Rows.Add(new object[] { "Grau", "Alkyd", "leicht" });
tblFarbe.Rows.Add(new object[] { "Schwarz", "Polyacryl", "nein" });
tblFarbe.Rows.Add(new object[] { "Weiss", "Polyacryl", "nein" });
tblFarbe.Rows.Add(new object[] { "Silber", "Alkyd", "nein" });
dg_Daten.ItemsSource = tblAutomobil.AsDataView();
}
/* ========================================================================================================================================================================*/
private void dg_Daten_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if(e.Column.Header.ToString() == "Lackfarbe")
{
e.Column = new DataGridComboBoxColumn
{
Header = "Lackfarbe",
ItemsSource = tblFarbe.AsDataView(),
DisplayMemberPath = "Farbe",
//// ==> Hier habe ich dann auch "Farbe" gesetz, ansonsten funktioniert das nicht
SelectedValuePath = "Farbe",
SelectedValueBinding = new Binding("Lackfarbe") { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged },
};
}
}
/* ========================================================================================================================================================================*/
}
}
Das ganze funktioniert noch nicht wenn ich das auf mein reeles Problem beziehe, da habe ich das ganze auch schon ausprobiert. Dort ist es allerdings so, das ich zwei Tabellen sozusagen zusammenvereine, aber nicht direkt schon mit "JOIN" in SQL verknüpfe, sonder das im Code mache. Eventuell liegt das Problem da, ich brauche da noch etwas Zeit um das nochmal genau zu analysieren und daran zu tüfteln / verändern. Ich melde mich mit dem konkreten Problem, aber zuerst möchte ich mich noch selber etwas mehr damit auseinandersetzen, das Problem dann auch mit vereinfachtem Code aufbauen damit ich das dann auch einfach und Übersichtlich in das Forum stellen kann.
Ich möchte euch jedenfalls erst mal schon für eure Hilfe und Mühe danken.
Sorry, nochmal zum Verständis zum vorgen Post von BlonderHans:
Muss nochmal erklären wie das ganze funktionieren oder aussehen soll. Ich probiere das nochmal ganz einfach anhand von zwei Datentabellen.
Tabelle "Automobildaten". Diese hätte 5 Spalten (Hersteller, Baujahr, Lackfarbe, Kilometerstand).
Hersteller | Baujahr | Lackfarbe | Kilometerstand |
---|---|---|---|
VW | 2015 | Blau | 50000 |
BMW | 2012 | Grau | 100000 |
BMW | 2019 | Schwarz | 30000 |
MERCEDES | 2018 | Weiss | 40000 |
OPEL | 2020 | Silber | 50000 |
Dann gibt es die Tabelle "Karosseriefarbe" mit den Spalten (Farbe, Farbzusatz, Pigmentierung) :
Farbe | Farbzusatz | Pigmentierung |
---|---|---|
Blau | Alkyd | leicht |
Grau | Alkyd | leicht |
Schwarz | Polyacryl | nein |
Weiss | Polyacryl | nein |
Silber | Alkyd | leicht |
Jetzt will ich diese Tabelle Automobildaten in einem DataGrid anzeigen lassen. Die Spalte Lackfarbe soll eine DataGridComboBox sein, damit ich in dieser die Items der Tabellenspalte Karosseriefarbe.Farbe anzeigen kann.
Jetzt kommt das ABER wo ich mit nicht sicher bin ob ihr mich korrekt verstanden habt:
Ist die Tabelle "Automobildaten" geladen und die Daten werden im DataGrid angezeigt, dann soll in der Spalte "Lackfarbe" die diese gespeicherten Werte dieser Tabelle angezeigt werden. Die Items der DataGridComboBox werden poppen erst auf, wenn ich auf eines dieser Control der Spalte "Lackfarbe" klicke.
Was möchte ichmit diesem Szenarion erreichen ==> Neue Datensätze die angezeigt werden und noch keine Festlegung von "Lackfarbe" haben, können somit vom User über die DataGridComboBox mit Daten bestückt werden. Der User sieht auch sofort, wo noch Daten nachzutragen sind.
Hallo TH69, habe nochmals die Variante von dir als auch von BlonderHans geprüft. Beides mal bleibt die Textbox leer, aber die ComboBox-Items sind befüllt.
Ich habe auch mal nach der Erzeugung der Spalte mir ihren Eigenschadften angesehen (als DataView zugewisen). Die Spalten sind in der LinQ-Abfrage auch vorhanden, aber diese ComboBox-Items sind ja nicht das Problem, sondern der Spaltenwert der normal im Datensatz drin steht. Wenn ich mir diese View ansehe und die ItemSource vom DataGrid, dann passt das auch, in der Spalte "Anschnittscheibe" steht der Wert 7778888 drin, wird aber nicht angezeigt.
Kann es sein das wie an die TextBox der Spalte binden müssen??
Habe noch Bilder beigefügt, von der DataView der Items und dem Aussehen des DataGrids.