Hallo 🙂
Kurz vorweg, ich bin Anfänger auf dem Gebiet der C#/WPF Programmierung, also bitte nich zu sehr haten =) Ich bin Systemadministrator und kein gelernter Programmierer.
Für mein Unternehmen bin ich derzeit dabei ein kleines Programm zu schreiben, was alle User die auf einen bestimmten Ordner auf einem Netzlaufwerk NTFS Rechte haben, auflistet. Sprich ich möchte sehen, wer z.B. auf G:\Verwaltung\Aufträge Lese- und Schreibrechte hat, und dies dann in einer Tabelle aufgelistet haben. Die erste Erleichterung: Mein Programm ist so gut wie fertig. Ich lasse mir alle AD-Gruppen für einen Ordner auslesen und lese dann aus diesen AD-Gruppen wiederum alle User aus. Die Benutzer werden in einer DataTable gespeichert und dann im Programm an ein DataGrid weitergegeben. Bedingt durch unsere ActiveDirectory-Architektur kommt es vor, dass User auf einen Ordner mehrmals über verschiedene Gruppen Lese-Schreibberechtigung bekommen. Bedeutet also, in meiner Tabelle habe ich Duplikate. Nun möchte ich diese doppelten Zeilen löschen, so dass nur noch eine da ist. Der Knackpunkt ist aber, dass für Duplikate in Spalte 1 unterschiedliche Werte in Spalte 4 und 5 stehen können. Die Spalte 1 mit der Mitarbeiter-Nummer ist hierbei eindeutig. Wie filtere ich jetzt die DataTable, dass sie mir das gewünschte Ergebnis anzeigt ?
Beispiel:
User für G:\Verwaltung\Aufträge
155484 |Max | Mustermann | Lesen | verwaltung-read
154574 |Klaus | Müller | Lesen | verwaltung-read
154574 |Klaus | Müller | Schreiben | administratoren
Was ich haben möchte:
155484 |Max | Mustermann | Lesen | verwaltung-read
154574 |Klaus | Müller | Lesen, Schreiben | verwaltung-read, administratoren
Ich habe hier aktuell eine Funktion, welche mir zuverlässig Duplikate entfernt, jedoch werden dadurch keine Zellen aus Spalte 4 und 5 gemerged
public DataTable RemoveDuplicateRows(DataTable dTable, string colName)
{
Hashtable hTable = new Hashtable();
ArrayList duplicateList = new ArrayList();
//Add list of all the unique item value to hashtable, which stores combination of key, value pair.
//And add duplicate item value in arraylist.
foreach (DataRow drow in dTable.Rows)
{
if (hTable.Contains(drow[colName]))
{
duplicateList.Add(drow);
}
else
{
hTable.Add(drow[colName], string.Empty);
}
}
//Removing a list of duplicate items from datatable.
foreach (DataRow dRow in duplicateList)
{
dTable.Rows.Remove(dRow);
}
//Datatable which contains unique records will be return as output.
return dTable;
}
Vielleicht kann mir ja jemand helfen 😁
Liebe Grüße
WPF ist so konzipiert, dass Daten gebunden werden ([Artikel] MVVM und DataBinding).
Agierst Du direkt in der UI ohne Bindung, wirst Du in WPF von Fallstrick zu Fallstrick stolpern.
WinForms war da gutmütiger, auch wenn dort auch schon Binding das richtige Mittel der Wahl war.
Besser wäre es, wenn Du die Nutzer in einer Liste führen würdest und diese Liste bearbeiten würdest.
Die Liste kannst Du dann an die UI Binden und wird jederzeit aktualisiert (automatisch), sobald sich die Liste (oder deren Inhalte) ändert.
Sie selbst ist natürlich dann mit allen Mitteln manipulierbar (Filter, Sortierung...).
Dazu musst Du aber MVVM anwenden.
Kleine Hinweise:
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Wenn du -wie Abt schreibt- Modellobjekte verwendest bist du flexibler da sie beispielsweise Methoden enthalten können und somit Verhalten kapseln können.
Bei deinem Problem könnte man LINQ verwenden also funktionale Programmierung. Mit Modellobjekten könnte das so aussehen (DataTables unterstützen auch LINQ muss man fairerweise zugeben):
public class GrantedAccess
{
public string Id { get; set; }
public string Surname { get; set; }
public string Name { get; set; }
public string Accesstype { get; set; }
public string Group { get; set; }
}
static void Main(string[] args)
{
var list = new List<GrantedAccess> {
new GrantedAccess { Id = "155484", Surname = "Max", Name = "Mustermann", Accesstype="Lesen", Group="verwaltung-read" },
new GrantedAccess { Id = "154574", Surname = "Klaus", Name = "Müller", Accesstype="Lesen", Group="verwaltung-read" },
new GrantedAccess { Id = "154574", Surname = "Klaus", Name = "Müller", Accesstype="Schreiben", Group="administratoren" }
};
var result = list.GroupBy(p => p.Id)
.Select(p => new GrantedAccess { Id = p.Key,
Surname = p.Select(q => q.Surname).First(),
Name = p.Select(q => q.Name).First(),
Accesstype = string.Join(", ", p.Select(q => q.Accesstype).Distinct().ToArray()),
Group = string.Join(", ", p.Select(q => q.Group).Distinct().ToArray()) })
.ToList();
result.ForEach(p => Console.WriteLine($"{p.Id}|{p.Surname}|{p.Name}|{p.Accesstype}|{p.Group}"));
Console.ReadLine();
}
Hmm... wahrscheinlich verstehe ich es nur falsch, aber ich war eigentlich der Meinung, ich hätte das mit dem DataBinding gemacht. Sobald ich was in der DataTable ändere, ändern sich auch die Daten im DataGrid.
public DataTable dt { get; private set; } = new DataTable();
private void Datagrid_Loaded(object sender, RoutedEventArgs e)
{
dt.Clear();
dt.Columns.Add("IDM-Nummer", typeof(string));
dt.Columns.Add("Vorname", typeof(string));
dt.Columns.Add("Nachname", typeof(string));
dt.Columns.Add("Berechtigung", typeof(string));
dt.Columns.Add("Gruppe", typeof(string));
Datagrid.ItemsSource = dt.DefaultView;
}
<DataGrid Grid.Row="1" x:Name="Datagrid" GridLinesVisibility="None" HeadersVisibility="Column" SelectionMode="Single" IsReadOnly="True" ItemsSource="{Binding}" Loaded="Datagrid_Loaded"/>
Den Aspekt, dass man keine DataTable mehr verwenden soll, sondern lieber eine List, werde ich mir nochmal anschauen.
.) Ich lasse mir alle AD-Gruppen für einen Ordner auslesen und lese dann aus diesen AD-Gruppen wiederum alle User aus.
.) Die Benutzer werden in einer DataTable gespeichert und dann im Programm an ein DataGrid weitergegeben.
Hallo,
wie schon von den Vorrednern gepredigt, sollte man hier eher Klassen-Objekte erstellen, die so einen gewünschten Datensatz wie du ihm haben willst, aufgebaut ist.
Und anstatt jetzt den 2ten Punkt dazu zu verwenden, die Daten in eine DataTable zu schreiben, befüllst du einfach jeden Benutzer in ein so eine Klasse und hast als Ergebnis eine Liste mit Benutzern die jeweils in Klassen sitzen 😁
Unter Umständen kannst du schon beim Befüllen der Klassen mit einer eindeutigen Id in jedem Schleifendurchlauf nach einer vorhandenen Klasse mit derselben Id in der Liste suchen. Wenn gefunden ergänzt du einfach die Daten, ansonsten erstellst einfach wieder eine neue Klasse.
Somit bekömmst du dann schon die fertig anwendbare Klassenliste aller Benutzer.
Diese Liste kann man dann genauso an das DataGrid oder andere Controls binden...
Grüße
Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄
Kleinigkeiten:
public class GrantedAccess { public string Id { get; set; } public string Surname { get; set; } public string Name { get; set; } public string Accesstype { get; set; } public string Group { get; set; } }
So würde ich das Modell auch gestalten, mit der Ausnahme:
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Ich werde mal etwas rumprobieren und mich dazu belesen.
Vielen Dank erstmal an alle 😃
Liebe Grüße