Technische Informationen rund um das Thema Modernes Arbeiten

Kategorie: C#

UWP: dynamische Grids mit c#

UWP: dynamische Grids – dieses Mal wieder eher ein sehr technisches Thema. Eigentlich wollte ich mal nur ganz kurz etwas ausprobieren. Doch dann fing die Suche an: wie erstellt man in einer Universal Windows Platform App eigentlich ein dynamisches Grid. 

Ziel war es, ein Formular mit folgendem Aussehen zu erhalten: 

Da ich das Formular aus einer Steuerdatei aufbauen wollte, waren die Parameter wie Textfeld-Inhalt, Inhalt von Frage 1 – 4 sowie der Yes/No-Buttons nicht von Anfang an definiert. Daher entschied ich mich, das Grid dynamisch mit C# aufzubauen.

Ich habe dazu viele Artikel gefunden. Letztendlich musste ich aber immer wieder feststellen, dass der letzte – wahrscheinlich entscheidende – Schritt fehlte. 

Hier meine Erkenntnisse:

Aufbau des Grids:

Grid gGrid = new Grid();
// Grid-Eigenschaften
gGrid.Width = 1000;
gGrid.Height = 700;

Anlage der Spalten:

ColumnDefinition spalte1 = new ColumnDefinition();
ColumnDefinition spalte2 = new ColumnDefinition();
ColumnDefinition spalte3 = new ColumnDefinition();

spalte1.Width = new GridLength(0, GridUnitType.Auto);
spalte2.Width = new GridLength(0, GridUnitType.Auto);
spalte3.Width = new GridLength(1, GridUnitType.Auto);

gGrid.ColumnDefinitions.Add(spalte1);
gGrid.ColumnDefinitions.Add(spalte2);
gGrid.ColumnDefinitions.Add(spalte3);

Aufbau der Zeilen

Nach der Definition der Zeilen habe ich mich an den Aufbau der Zeilen gemacht. Die Anzahl der Zeilen wurden durch die Steuerdatei festgelegt.

Wenn man nach UWP und dynamische Grid sucht, findet man wenig über die Anlage von Zeilen. Dies war meine Lösung für die Anlage von Zeilen (in dem Beispiel die Anlage von 2 Zeilen)

var tabellenZeile1 = new RowDefinition();
tabellenZeile1.Height = GridLength.Auto;
gGrid.RowDefinitions.Add(tabellenZeile1);

var tabellenZeile2 = new RowDefinition();
tabellenZeile2.Height = GridLength.Auto;
gGrid.RowDefinitions.Add(tabellenZeile2);

Füllen mit Inhalten

Nun ging es darum, die Zeilen mit Inhalt zu füllen. Meine Elemente (wie im Screenshot gezeigt) waren:
1. ein Textfeld
2. ein Radiobutton z. B. mit „Yes“
3. ein Radiobutton z, B, mit „No“

Das Textfeld (qKatalog ist eine Liste, die den Inhalt der eingelesenen Rohdaten enthält): 

Tb_Answer1.Text = qKatalog[iPos].answer1;
Tb_Answer1.Width = 774;
Tb_Answer1.HorizontalAlignment = HorizontalAlignment.Left;
Tb_Answer1.Margin = new Thickness(10);

Radiobuttons

Danach werden die beiden Radio-Buttons erzeugt und einer Gruppe zugeordnet:

RadioButton RB_Y1 = new RadioButton();
RadioButton RB_N1 = new RadioButton();

RB_Y1.Content = qKatalog[iPos].lText1;
RB_Y1.GroupName = "YN1";
RB_Y1.HorizontalAlignment = HorizontalAlignment.Left;

RB_N1.Content = qKatalog[iPos].lText1;
RB_N1.GroupName = "YN1";
RB_N1.HorizontalAlignment = HorizontalAlignment.Left;

Anordnen im Grid

Nun kommt ein wichtiger Schritt, der in vielen Beschreibungen gefehlt hatte: 

gGrid.Children.Add(Tb_Answer1);
gGrid.Children.Add(RB_Y1);
gGrid.Children.Add(RB_N1);

Damit sind die Elemente dem Grid zugeordnet. 

Anschließend müssen die Inhalte „nur“ noch den entsprechenden Zeilen und Spalten zugeordnet werden:

Grid.SetRow(Tb_Answer1, 0);
Grid.SetRow(RB_Y1, 0);
Grid.SetRow(RB_N1, 0);

Grid.SetColumn(Tb_Answer1, 0);
Grid.SetColumn(RB_Y1, 1);
Grid.SetColumn(RB_N1, 2);

Das bedeutet, dass die Elemente der Zeile (SetRow) 0 zugeordnet wurden. Danach werden Tb_Answer1 in die Spalte 0, RB_Y1 in die Spalte 1 und RB_N1 in die Spalte 2 platziert.  

Danach müssen eigentlich nur noch die weiteren Zeilen mit Inhalt gefüllt werden.

 

Die genutzten Quellen: 

 

Auf Office 365 Benutzer programmatisch zugreifen

Erst einmal vorweg: ich bin kein Entwickler. Insofern kann sicher vieles einfacher oder einfach anders gemacht werden… Aber: es funktioniert.

Trotzdem habe ich mich getraut, mich durchzukämpfen: Ich hatte die Anfoderung, dass ich für unsere Demo-Umgebung regelmäßig mehrere Benutzer in Office 365 ändern musste. Da dabei auch z. B. die Domäne – und damit der Anmeldename und u. U. auch das Passwort des Benutzers geändert werden musste – verfiel ich auf die Idee, ein kleines Programm in C# anzulegen, das es mir erlaubte, alle Benutzer, die eine Lizenz haben aus einem aktiven Office 365 – Tenant auszulesen und mit neuen Daten (Anmeldename, Vor-/Nachname sowie wenn gewünscht neuem Passwort) wieder zu speichern.
Ich habe viel Zeit gebraucht, um in den verschiedenen Foren Lösungen zu finden – aber letztendlich habe ich dann die nötige Information gefunden und konnte daraus mein eigenes kleines Programm schreiben.

Im ersten Schritt werden die Grundinformationen erfasst:

  • Wie heißt der Tenant
  • Wie heißt der Admin-User
  • Passwort des Admin-Users
  • Soll eine neue Domäne vergeben werden? (muss dem Tenant aber schon zugeordnet sein)
  • Soll ein neues Passwort vergeben werden?
  • Wie soll der Benutzername aufgebaut sein?

Über den Button „Load“ können dann die Benutzer aus Office 365 geladen werden.

Anschließendkönnen den Benutzern neue Vor- und Nachnamen zugeordnet werden.

Über den „Change“-Button werden die Benutzer, die neue Namen zugeordnet bekommen haben, in Office 365 zurückgeschrieben.

Viele der gefundenen und genutzten Codefragmente stammen aus dem DEV Center von Microsoft oder von MSDN. So wird z. B.

und weiteren öffentlich zugänglichen Quellen genutzt.

Für das Programm werden folgende Bibliotheken genutzt:

[code language=“csharp“]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.SharePoint.Client;
using System.Collections.ObjectModel;
using System.Security;
[/code]

Nachdem in die Felder die notwendige Information eingegeben wurde und der Load-Button angeklickt wurde, werden die Daten aus dem Office 365 Tenant ausgelesen:

[code language=“csharp“]

/// <summary>
/// Erzeugen einer temporären Benutzerliste.
/// </summary>
/// <param name=“sender„></param>
/// <param name=“EventArgs„></param>
/// <return value=“void“></return>

private void BT_PeopleLoad_Click(object sender, EventArgs e)
{
try
{
Cursor.Current = Cursors.WaitCursor;
UserCredential.UserName = TB_User.Text;
UserCredential.Password = get_password();
// Befehl zum Verbinden mit Officee 365 wird erstellt.
List<Command> psCommand = new List<Command>();    
// Anlegen des Initial Session State
InitialSessionState initialSession = InitialSessionState.CreateDefault();
initialSession.ImportPSModule(new[] { „MSOnline“ });
// Anlegen des CredentialObjects
PSCredential credential = new PSCredential(UserCredential.UserName, UserCredential.Password);
// Erzeugen des Befehls zum Verbinden mit Office 365.
 psCommand.Add(new Command(„Connect-MsolService“));
 psCommand[0].Parameters.Add((new CommandParameter(„Credential“, credential)));
// Erzeugen des Befehls zum extrahieren der Office 365 Benutzer.
 psCommand.Add(new Command(„Get-MsolUser“));
// Ermitteln der Benutzerliste innerhalb des Tenants.
Collection<PSObject> results = execute_ps(psCommand);
if (results != null && results.Count > 0)
{
FillUserList(results);      // Benutzerliste wird gefüllt
}
else
{
Cursor.Current = Cursors.Default;
return;
}
Cursor.Current = Cursors.Default;
    }
 catch (Exception ex)
{
Cursor.Current = Cursors.Default;
MessageBox.Show(ex.Message);
return;
}

 }

[/code]

Das Passwort wird in der Routine get_password() generiert – Ziel ist es, einen Secure-Passwort-String zu übergeben:

[code language=“csharp“]

/// <summary>
/// Erstellen eines sicheren Passwort-Strings
/// </summary>
///
/// <return value=“SecureString“></return>

private SecureString get_password()
{
SecureString passWord = new SecureString();
foreach (char c in TB_Password.Text.ToCharArray()) passWord.AppendChar(c);
return passWord;
}

[/code]

Nun werden (neben dem Aufbau und Ausgabe der Tabelle) eigentlich nur noch eine wichtige Routine benötigt:  Sie führt die Powershell Skripte aus…

 

[code language=“csharp“]

/// <summary>
/// Execute PowerShell Skripts. Übergeben wird ein Array mit PowerShell Befehlen
/// </summary>
/// <param name=“psCommand„></param>
/// <return value=“Collection“></return>
private Collection<PSObject> execute_ps(List<Command> psCommand)
{
UserCredential.UserName = TB_User.Text;
UserCredential.Password = get_password();
 // Anlegen der Initialen Session.
InitialSessionState initialSession = InitialSessionState.CreateDefault();
 initialSession.ImportPSModule(new[] { „MSOnline“ });
using (Runspace psRunSpace = RunspaceFactory.CreateRunspace(initialSession))
{
Collection<PSObject> results = null;
// runspace öffnen.
psRunSpace.Open();
//Durchlaufen der Liste mit den Befehlen – und Ausführung der Befehle.
 
foreach (var com in psCommand) // new Command[] { connectCommand, getUserCommand, setUserPName }
{

    var pipe = psRunSpace.CreatePipeline();
pipe.Commands.Add(com);

    // Ausführen des Befehls – Analyse etwaiger Fehler.
results = pipe.Invoke();

   var error = pipe.Error.ReadToEnd();
if (error.Count > 0) //&& com == connectCommand)
{

        MessageBox.Show(error[0].ToString(), „Problem beim login“);
return results;
}

   }

  // Runspace schließen.
   psRunSpace.Close();

   return results;
}

}

[/code]

Der Rest der Anwendung besteht darin, die Tabelle zu füllen, die Änderungen dann wieder aus der Tabelle auszulesen und als Skript wieder an execute_ps zu übergeben.

Als Zielpunkte der Skripte werden folgende Powershell-Skripte genutzt:

  • Connect-MsolService
  • Set-MsolUser (um die Änderungen am Benutzer durchzuführen)
  • Set-MsolUserPrincipalName
  • Set-MsolUserPassword

Wichtig ist, dass bei der Übergabe der Skript-Befehle weitergehende Parameter als „Parameters“ übergeben werden, beispielhaft hier mit Set-MsolUserPrincipalname dargestellt.

[code language=“csharp“]

psCommand.Add(new Command(„Set-MsolUserPrincipalName“));  // Powershell – Befehl
psCommand[2].Parameters.Add((new CommandParameter(„-UserPrincipalName“, old_cUserName + „@“ + domains[1]))); // Parameter -UserPrincipalName
psCommand[2].Parameters.Add((new CommandParameter(„-NewUserPrincipalName“, new_UserPrincipalName))); // Parameter -NewUserPrincipalName

[/code]

Der entsprechende Powershell – Befehl hierzu lautet:

[code language=“powershell“]

Set-MsolUserPrincipalName
-NewUserPrincipalName <String>
[-ImmutableId <String>]
[-NewPassword <String>]
-UserPrincipalName <String>
[-TenantId <Guid>]
[<CommonParameters>]

[/code]

Ich hoffe, das Beispiel hilft, um vergleichbare Themen schneller lösen zu können. Ich danke allen, die im Web so viel interessanten Beispielcode veröffentlicht haben. Das gesamte Projekt setzt sich aus einzelnen Teilen aus den oben genannten Beispielen zusammen.

 

© 2023 Modernesarbeiten

Theme von Anders NorénHoch ↑