Martin Lantzsch
Software Entwickler
26. Oktober 2013

C# WPF AbstractWindow

26. Oktober 2013 - Geschrieben von Martin - Keine Kommentare

Normalerweise erbt die Klasse eines neu erzeugten Fensters (in diesem Fall MainWindow) direkt von System.Windows.Window. Bei meiner Anwendung wollte ich allerdings, dass das Hauptfenster von meiner Klasse ResiWriter.UI.AbstractWindow erbt.

namespace ResiWriter.UI
{
    public abstract class AbstractWindow : System.Windows.Window
    {
 
    }
}

In der MainWindow.xaml.cs Klasse habe ich dann wie gewohnt von der AbstractWindow geerbt:

namespace ResiWriter
{
    public partial class MainWindow : UI.AbstractWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Durch den Umstand, dass MainWindow eine partial Klasse ist, muss nun auch der zweite zugehörige Klassenteil vom AbstractWindow erben. Problematisch an der Sache ist jedoch, dass der zweite Teil der Klasse beim kompilieren aus dem XAML erzeugt wird. Dementsprechend muss dieses XAML angepasst werden um dem Compiler mitzuteilen von welcher Klasse geerbt werden soll.

<src:AbstractWindow x:Class="ResiWriter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:src="clr-namespace:ResiWriter.UI"
        Title="ResiWriter" Height="480" Width="800">
        <Grid></Grid>
</src:AbstractWindow>

Wichtig ist hier, dass der Knoten Window durch src:AbstractWindow getauscht wird. Damit der Compiler auch weiß aus welchem Namespace AbstractWindow stammt wird zusätzlich das Attribut src eingefügt: xmlns:src=“clr-namespace:ResiWriter.UI“

21. Oktober 2013

/bin/false und vsftpd

21. Oktober 2013 - Geschrieben von Martin - Keine Kommentare

Wenn ein User Account die Shell /bin/false zugewiesen bekommt hat er keinen Zugriff mehr auf die Shell, was sich zum Beispiel bei einem File Server anbietet, auf dem User selbst quasi keine Rechte haben.

chsh -s /bin/false USER

Nutzt man nun diesen User Account zur Authentifizierung am vsftpd so schlägt jeder Login fehl, da vsftp eine gültige Shell verlangt.

Um dies zu umgehen kann man in der Konfiguration von pam.d die Überprüfung auf eine gültige Shell exklusiv für vsftpd abschalten:

nano /etc/pam.d/vsftpd

# Standard behaviour for ftpd(8).
auth    required        pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
 
# Note: vsftpd handles anonymous logins on its own. Do not enable pam_ftp.so.
 
# Standard pam includes
@include common-account
@include common-session
@include common-auth
#auth   required        pam_shells.so

Die letzte Zeile wie hier auskommentieren und schon kann man sich mit dem Benutzer am FTP Server anmelden.

5. Oktober 2013

Multitasking in einer Web App

5. Oktober 2013 - Geschrieben von Martin - 2 Kommentare

Momentan spiele ich mit der Idee eine Art CRM Web App zu entwickeln in der Kunden, Aktivitäten, Projekte, etc. verwaltet werden können. Bei den ersten Entwürfen der GUI stellt sich mir allerdings die Frage wie man am besten Multitasking in einer Web App abbildet.

Sieht man sich bekannte Web Anwendungen an so wird man feststellen, dass alle folgendem alt bekannten Schema folgen:

  • Dokument suchen
  • Dokument öffnen
  • Dokument bearbeiten
  • Dokument schließen
  • … und wieder von vorn

Das ganze läuft in einem Browserfenster ab und es ist lediglich der momentane Arbeitsschritt durchführbar.

Beobachte ich nun aber meine Arbeitsweise so bearbeite ich allerdings meist mehrere Dokumente oder lese diese zumindest, denn den Idealfall dass man sequenziell die Arbeit verrichtet habe ich noch nie erlebt. Immer wieder kommt eine Kundenabfrage die bearbeitet werden will oder der Kollege der zwischen Tür und Angel steht benötigt jetzt eine Auskunft. Und wenn man noch tiefer geht gibt es meist auch zwischen den Akten Abhängigkeiten, zum Beispiel muss in einem älteren Dokument ein Detail nachgesehen werden um das jetzige fertigstellen zu können.

Diese Fälle sind eben in jenen klassischen Anwendungen nicht berücksichtigt, hier muss man ständig den Bearbeitungsmodus verlassen und später wiederkehren. Sehr produktiv.

Als „Workaround“ können natürlich mehrere Browserfenster oder Tabs geöffnet werden, allerdings hat dies bei vielen Anwendungen markante Nachteile, zum Beispiel bleibt ein Tab der seit Stunden offen ist unaktualisiert was den unerfahrenen Nutzer verwirren kann – „dieses Ticket habe ich doch bereits geschlossen?“, diese Benutzerschicht wird auch oft verwirrt durch immer gleiche Fenster die sich nur im Detail unterscheiden – so sind Navigationselemente, Listen und Formulare über all die selben, die Seiten unterscheiden sich nur in den angezeigten Daten.
Doppelte Elemente haben auch zur Folge, dass sie Bildschirmplatz verschwenden wenn mehrere Browser Fenster nebeneinander gestellt werden um eine Mail zu auf Basis von Ticket Inhalten zu verfassen.

Auch bei WordPress wird sichtbar wie Platz verschwendet wird. Rot doppelte Elemente, Grün die der eigentliche Inhalt.Auch bei WordPress wird sichtbar wie Platz verschwendet wird. Rot doppelte Elemente, Grün die der eigentliche Inhalt.

Doch wie löst man das Problem?
Ehrlich gesagt habe ich hierfür noch keine perfekte Lösung gefunden, allerdings ziemlich gute, doch später mehr. In letzter Zeit gehen viele Anwendungen den weg, dass sie im Browserfenster weitere Fenster emulieren (emulieren soll hier ausdrücken, dass es keine nativen Fenster sind wie z.B. Popups). In diesem Bezug haben sich viele Frameworks wie z.B. ExtJS und jQuery UI etabliert die sich großer Beliebtheit erfreuen. Ich will hier aber nicht über Frameworks berichten sondern über Usability.

Fenster im Browser zu emulieren finde ich ist eine ziemlich bescheidene Idee, denn so wirft man einen ziemlich wichtigen Punkt über Bord, der sich im Web über die Jahre gehalten hat. Die Führung des Nutzers durch einen unter umständen komplexen Prozess indem man einen Weg vorgibt. Der obige sequenzielle Ansatz der von vielen Web Apps benutzt wird, hat den Charm, dass man sich stets auf eine Aktion konzentriert und diese nicht aus den Augen verliert. Fenster sorgen wieder dafür, das man wichtiges aus den Augen verliert und abgelenkt wird. Auch gestaltet sich die Führung eines Users durch verkettete Fenster schwer. Viele behelfen sich hier mit aufpoppenden Dialogen die andere Fenster blockieren um den User zu einer Aktion zu zwingen. Hier haben wir also wieder die Situtation in der der Nutzer ledigliche eine Aktion ausführen kann und diese beenden muss bevor er weitere in Angriff nehmen kann.

ExtJS Multitasking

Und was ist mit Tabs? Tabs sind in der Tat die bessere Wahl, sie zeigen immer nur eine Aktion, der Benutzer weiß aber das er zwischen mehreren wechseln kann ohne Daten zu verlieren (sehr wichtig!). Beispielsweise kann eine Email in einem Tab verfasst werden und per klick auf einen Menüpunkt öffnet sich ein weiterer mit einer Kundenliste um Informationen für die aktuelle Email zu suchen. Natürlich können viele Tabs auch sehr verwirrend werden, deshalb sollte eine durchdachte Tab Verwaltung auch Gruppierung nach Aktion oder Kunde ermöglichen.

Ein meines Erachtens nach sehr gutes Beispiel für solch eine Oberfläche ist die vom OpenExchange Projekt entwickelte OX App Suite um in diesem Artikel auch noch ein Beispiel für Experementierfreudige zu liefern. Hier dient ein einfaches Menü zur Navigation durch die verschiedenen Anwendungen und die aktuellen Aktionen werden durch Tabs abgebildet.
OX AppSuite 1

Wichtige Informationen wie Benachrichtigungen können ohne Verlassen eines Menüpunktes oder Tabs durch ein Overlay eingeblendet werden:
OX AppSuite 2

Und viele Anwendungen sind weit verschachtelt ohne auch nur einen Tab zu öffnen, das nervt den Nutzer nicht mit vielen unnötigen Tabs die er wieder schließen muss.
OX App Suite 3

Re­sü­mee
Kurz um – versucht nicht alt bewährte Window Manager im Web nachzubauen. Auch wenn es Frameworks einfach machen, denkt daran was eure Nutzer wollen – eine Übersichtliche Anwendung die einfach zu bedienen ist und Spaß macht! Diese Punkte haben dem Web zu dem verholfen was es heute ist und nicht RIAs die seit jeher versuchen den Browser als plattformunabhängige Runtime zu missbrauchen.

30. September 2013

Einen JavaScript Array erkennen

30. September 2013 - Geschrieben von Martin - Keine Kommentare

Gerade habe ich beim Code Review folgenden Code gesehen:

typeof [1, 2, 3] === 'array'

Von der Logik her okay, aber halt! Ein JavaScript Array ist doch ein Objekt? Und ja ein schneller Hack auf der Konsole sagt uns

typeof [1, 2, 3]
=> "object"

Ergo müssen wir prüfen ob das Objekt eine Instanz von Array ist

[1, 2, 3] instanceof Array
=> true

29. August 2013

ExtJS Store AJAX Proxy HTTP Basic Authorization

29. August 2013 - Geschrieben von Martin - Keine Kommentare

Um Daten von einem Webservice abzurufen, der mittels HTTP Basic Authorization gesichert ist muss dem AJAX Proxy ein Header mitgegeben werden, der die Base64 encodeten Zugangsdaten enthält. Dies habe ich bei meinem Store direkt in den Konstruktor geschrieben:

constructor: function(config) {
    this.proxy.headers = {
        'Authorization': 'Basic ' + window.btoa(config.username + ':' + config.password)
    };
    this.callParent(config);
}

im Gesamten dann etwa so:

Ext.define('Resi.stores.Mails', {
    proxy: {
        type: 'ajax',
        url: 'api/mails'
    },
    constructor: function(config) {
        this.proxy.headers = {
            'Authorization': 'Basic ' + window.btoa(config.username + ':' + config.password)
        };
        this.callParent(config);
    }
});

Die verwendete window.btoa ist leider nur in neuen Browsern verfügbar, sollten auch ältere Browser später diese Anwendung nutzen sollen, muss hier eine Base64 Bibliothek eingebunden werden.

var Mails = Ext.create('Resi.stores.Mails', { 
    username: 'Resi',
    password: 'Mein sicheres Passwort'
});

25. August 2013

Standard PHP Library (SPL) Beispiele

25. August 2013 - Geschrieben von Martin - Keine Kommentare

Ich habe festgestellt das viele Leute kaum Bestandteile aus der SPL (Standard PHP Library) nutzen. Wahrscheinlich weil die Dokumentation auf php.net ein wenig zu wünschen übrig lässt. Aus diesem Grund habe ich vorhin begonnen ein paar Beispiele zu schreiben, die den korrekten Einsatzzweck von SPL Klassen nicht nur erahnen lassen sondern auch an teilweise Real World Szenarien zu verstehen helfen.

Das ganze ist auf GitHub in meinem Repository SPL-Examples zu finden.

21. Juli 2013

Unscharfe Schrift im Firefox fixen

21. Juli 2013 - Geschrieben von Martin - Keine Kommentare

Da ich nun anstatt dem Datensaugenden Google Chrome wieder Firefox installiert habe hatte ich auf meiner Windows 8 Maschine das Problem, dass die Schriften allsamt unscharf waren und Bild Fragmente aufwiesen, dies konnte ich über folgenden Workaround fixen:

  1. Zu about:config navigieren
  2. Den Key gfx.content.azure.enabled suchen
  3. Den Wert von true auf false stellen

das war es schon, nun sollten die Schriften wieder stimmig sein.

9. Juli 2013

EntityFramework Code First POCO Schnelleinstieg

9. Juli 2013 - Geschrieben von Martin - Keine Kommentare

1. per NuGet das Entity Framework Paket nachinstallieren
EntityFramework NuGet

2. Datenquelle (Connectionstring) in der App.config hinterlegen

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- schnipp -->
  <connectionStrings>
    <add name="UserDatabase"
         providerName="System.Data.SqlServerCe.4.0"
         connectionString="Data Source=User.sdf"/>
  </connectionStrings>
</configuration>

3. Model erstellen

class User
{
    public int Id { get; set; }
    public String Firstname { get; set; }
    public String Lastname { get; set; }
}

4. Context erstellen

class UserContext : DbContext
{
    public UserContext() : base("UserDatabase")
    {}
 
    public DbSet<User> Users { get; set; }
}

5. Verwendung des Contextes zum erstellen eines Datensatzes

using (var context = new UserContext())
{
    User user = new User { Firstname = "Martin", Lastname = "Linux" };
    context.Users.Add(user);
    context.SaveChanges();
    Console.WriteLine(user.Firstname);
    Console.ReadLine();
}

EntityFramework Ausgabe

6. Daten einsehen über den Server Explorer

  • Server Explorer über Ansicht – Server-Explorer öffnen
  • Rechtsklick auf Datenverbindungen dann Verbindung hinzufügen
  • Datenbankdatei aus dem Projektbinverzeichnis wählen

EntityFramework Verbindung hinzufügen
EntityFramework Server Explorer