Windows 8 TextBox clear Kreuz

Das Kreutz mit dem Kreuz. In meiner letzten Windows 8 Store App (METRO) Schulung fragte mich ein Kurs Teilnehmer, warum in der Textbox kein Kreuz zu sehen ist um den Textinhalt zu löschen. Ich war mir sicher früher war das da

image

Technisch gesehen muss es sich dabei um einen Button innerhalb der Textbox handeln.

Da ich mir nicht sicher war ob da wieder XAML stiefmütterlich von den Entwicklern aus Redmond behandelt wurde, der Cross Check mit JavaScript und HTML (mit Überwindung). Und in der Tat, sobald man in der laufenden Anwendung Text eintippt erscheint das x mit dem der Inhalt der Textbox geleert werden kann.

image

Nun zurück zur XAML Store App. Mit Expression Blend kann man die Textbox gut in seine Bestandteile zerlegen und so den Deletebutton ausfindig machen.

image

Dieser Button ist in den Eigenschaften als Collapsed definiert und damit nicht sichtbar.

image

Man kann im XAML Source Code gut erkennen das einen eigene Stategroup  ButtonStates im VisualStateManager deklariert ist.

image

Jetzt gilt es nur mehr das Property zu finden das den Statuswechsel intern in der Textbox Logik auslöst und das Kreuz sichtbar macht.

   1:   <TextBox HorizontalAlignment="Left" Margin="55,37,0,0" 
   2:  TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="149"/>

Und der Übeltäter ist Textwrapping. Ohne diese oder mit NoWrap ist das x wieder da.

image

War das schon mal anders, in der Beta? Keine Ahnung, könnte sein. Ganz logisch ist es nicht.

XAML WebView Control

In einer Windows 8 Development Schulung kam die Frage auf das WebView Control. Dies eignet sich zum Anzeigen von HMTL und basiert auf dem IE 10. Nichts desto trotz ist es erheblich in seiner Funktion beschnitten. Mutmaßlich aus Gründen der Sicherheit, kann man in keiner METRO App ein XAML UI Element über das WebView Control legen. So wird ein Charme, der ja vom Betriebssystem kommt noch im Vordergrund erscheinen. Der weitere Settingsdialog ist aber hinter dem Webview Control und damit nicht sichtbar. Einziger Workaround für AppBar und Settings ist, das Webview einfach zu verkleinern, bzw. zu verschieben. Während man ein Popup dargestellt, sind diese beiden UI Elemente  dann nebeneinander.

Wenn man einen MessageDialog braucht, ist dieser Ansatz kaum zu machen. Üblicherweise werden dann statt dem Webview ein Bild der aktuellen Darstellung überblendet und das Webview deaktiviert. Dabei hilft der WebViewBrush.

Das folgende VB.NET Code Schnippsel ist aus dem Windows 8 Winrt SDK entnommen

 If Rect1.Visibility = Windows.UI.Xaml.Visibility.Visible Then
Dim b As New WebViewBrush() b.SourceName = "WebView6" b.Redraw() Rect1.Fill = b WebView6.Visibility = Windows.UI.Xaml.Visibility.Collapsed
End If

Als nächstes habe ich mich den Innereien zugewandt. Üblicher HTML und JavaScript Code funktioniert meist recht gut. Allerdings hat der IE 10 nach wie vor erhebliche Meinungsunterschiede wie der Standard HTML5/CSS3 und Java Script interpretiert werden sollen. Popup Dialoge wie alert oder confirm werden komplett unterdrückt.

In meiner Aufgabenstellung wollte ich ein Stück Text markieren und in der WinRT App weiter verwenden.  Es gibt zwar ein Event ScriptNotify, aber man muss vorher deklarieren für welche Quellen das gilt. Wenn man das vergisst wartet man vergeblich auf das Notification Event.

Private Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Dim uris = New List(Of Uri)
        uris.Add(New Uri("http://localhost:21916/"))
        webview1.AllowedScriptNotifyUris = uris
       AddHandler webview1.ScriptNotify, AddressOf JScriptEvent
 End Sub

Private Sub JScriptEvent(sender As Object, e As NotifyEventArgs)
        txtHTML.Text = e.Value

End Sub

Im JavaScript Teil ist der Aufruf mit einer Zeile Quellcode erledigt. Hier wird ein Button dazu verwendet. Allerdings musste ich Code klauen um den selektierten Text in den gängigen Browsern zu erhalten.

function ButtonSelectedText() 
{         
     window.external.notify(getSelText().toString());
}

function getSelText() {
           var SelText = '';
           if (window.getSelection) {
               SelText = window.getSelection();
           } else if (document.getSelection) {
               SelText = document.getSelection();
           } else if (document.selection) {
               SelText = document.selection.createRange().text;
           }
           return SelText;
 }

Bisher habe ich keine Möglichkeit gefunden aus WinRT heraus JavaScript im WebView Control zu debuggen.

Weiters sollte der selektierte Text per Context Menü übernommen werden können. Was im Browser noch funkltioniert verweigert im Webview seinen Dienst. Deswegen habe ich hier den Umweg über ein MouseUp Event verwendet um den markierten Text in einen Zwischenvariable gelegt.

<div class="context-menu-html5menu box menu-1">
    Context Menü das ist ein wenig mehr text und wir werden sehen
</div>
    <div id="out"></div>
    <menu class="showcase" id="html5menu" type="context" style="display: none;">
<command onclick="ContextMenuSelectText()" label="Markiert"></command>

<command onclick="some code ” label="Entfernen">
</
command>
</menu> <script> var txt='';
$(document).ready(function ()
{ $(document).bind("mouseup", function ()
{ txt = getSelText().toString(); }); }); $(function ()
{ $.contextMenu(
{ selector: '.context-menu-html5menu', items: $.contextMenu.fromMenu($('#html5menu')
) }); });



function ContextMenuSelectText()
{ window.external.notify(txt); }

 

 

 

 

Startbutton Total Egal

Gestern Abend habe ich mein sehnlichst erwartetes Surface Tablet in den Schrank gelegt und meinen knapp 3 Jahre alten Fujitsu T900 wieder hervorgeholt.

Mit knappen Worten: das ist es nicht, zumindest für mich.

Doch mal von vorne. Als bekennender Fan von Microsoft verdiene ich meine Brötchen damit, Werte auf die Produkte aus Redmond aufzustöpseln (added value) und damit diese beim Kunden zu Lösungen zu machen. Wie viele Millionen andere Menschen täglich. Ein Geschäftsmodell, dem ich ziemlich viel abgewinnen kann. Apple mit seinen strengen Regeln und Geheimnistuerei hat mich immer abgestoßen. LINUX mit seiner elitären leicht kommunistischen Eigendarstellung entspricht nicht meinen Bild von Wirtschaft.

Eine Plattform, smarte Leute, die Freiheit damit bauen zu können was man will. Ein bisschen Lego halt. Meine Welt.

Als bekennender Fan ( ich glaub der Leser hat Anrecht die politische Einstellung des Autors zu kennen) pilgerte ich genau vor einem Jahr zur //BUILD nach Los Angeles. Windows 8 erstmalig und beeindruckend. Dazu ein super Device um damit entwickeln zu können. Allerdings waren erste Schatten erkennbar. Warum dieser Hype um dieses schrottige JavaScript?

[FlashBack] Was habe ich gekotzt für ASP.NET JavaScript in den verschiedenen Browsern zu schreiben. Miese Editoren,  Debugging Hölle, Browser, langsam, groß, Sprachen, alles. Mit Silverlight 1 wurde in JavaScript “programmiert”. Wie toll war dagegen die Version 2 mit .net. [/FlashBack]

Warum dieses Geheimnistuerei? Warum ein closed Store Konzept? Was tut die ISV Branche die komplett eigene, teilweise konträre Geschäftsmodelle hat? Hat mein bei WP7 nicht gelernt, das APPLE kopieren gar nicht funktioniert? Und überhaupt wo ist die Liebe, die liebe zu uns Microsoft XAML Guys. Irgendwie hat man das Gefühl Microsoft schielt ausschließlich auf die andere Seite. Fachbegriff compete

Dann begann eine lange Zeit des Leidens. Viele Bugs. Doch wesentlich größere Unterschiede im Code als ursprünglich vermutet. Viele Kollegen und auch Microsoft Mitarbeiter sprechen unter der Hand mit mir und teilen die Einschätzung und wesentlich mehr. Infos die ich nicht teilen kann, weil Vertraglich verboten oder einfach aus Respekt vor meinem Gegenüber.

Wir haben investiert. Viele Samples geschrieben. Jede Menge Blog Einträge verfasst. Wir waren bereit.

Wir wollten Investieren. Alle unsere Schulungsräume auf Windows 8 Ready mit neuen Touch Monitoren ausstatten (und das sind hunderte). Schlicht es gibt keine zu kaufen. (Mir hallt noch der Spruch von der //BUILD Keynote – A device without touch – is a broken device).  Wir haben als treuer Windows 7 Fans ( auch das konnte man bereits ganz gut touchen) eine größere Anzahl All-In-One Devices von HP und Lenovo angeschafft. Mal erkennt der Touch Treiber nur einen statt zwei Punkte. Mal geht die Cam nicht. Support? Alles läuft wie bisher nur besser- broken.

Mein täglicher Begleiter der Fujitsu T900 mit Windows 8. SmartCase Logon +: crasht. Meine Webcam, geht native, aber nicht unter Windows 8 APPs. Mein Schocksensor- kein Treiber,mein wunderbares Dual Digitizer Display: Handballen Erkennung futsch: broken.

Gestern bei ALDI Nord ein neues Windows 8 Notebook für 499- ohne Touch Display: broken. Besuch bei Mediamarkt… wunderbarer Apple Stand, Windows 8: lassen wir das.

Kommen wir zum Shopping Erlebnis, Windows Surface bestellen. Die User Experience des Microsoft Stores benötigte von mir 44! Anläufe um das Gerät zu ordern. Der Service egal Telefon oder Chat: broken. Jetzt ist es da und es fehlt das Keyboard. Einhellige Meinung im Web: ihr hättet es Amazon machen lassen sollen. Die können das ( ein typischer Projekt Managment Fehler, Tasks im Projekt die man noch nie gemacht hat).

Zeitsprung: In der Zwischenzeit habe ich eine Windows 8 APP geschrieben (eigentlich viele), aber diese eine, wollte ich der Welt gratis zur Verfügung stellen. Nicht das übliche irgendein Service im Grid darstellen, sondern ein Share 2 Sharepoint. Also ein Foto ganz einfach nach SharePoint hochladen.

Die Entwicklung des Prototypen in Winforms hat ziemlich genau 40 Minuten gedauert. Das Umsetzen nach WinRT knapp 8 Stunden. Klar, es war dann noch der SettingsDialog dabei. Das Anwenden der Store Richtlinien weitere 2 Tage. Nach 7 erfolglosen versuchen, mit jeweils rund 7 Tagen Wartezeit, die APP zu veröffentlichen ist diese noch immer nicht im Store: broken. Der ganze Submission Prozess, entspringt einen zentralistischem, wir kontrollieren alles von USA aus Gedanken: broken

Gestern Nachmittag war es dann soweit. Das erste Mal Surface Tablet in den Händen halten. Auspacken, fühlen einschalten. Konfigurieren. Alles Super, Um Ecken besser wie meine erste iPad Experience

[Flashback] Alle reden davon, da muss was dran sein. Ein iPad muss her. Auspacken, einschalten. 64 MB downlod für Itunes –keine DVD?, Account konfigurieren, Kreditkarte eingeben- sonst keine Nutzung möglich WTF? Das Ding spiegelt wie Sau und was soll ich damit? Nach 2 h ins Eck [/Flashback]

Klein leicht, schick sexy, 2 Kameras, Ständer, USB, Bluetooth, usw. Alles cool. Ausstattung, Software passt. Überraschenderweise sogar Desktop APP. Die Kollegen sind begeistert. “Will auch haben”

[Zuhause]

Hmm was mach ich jetzt damit. Ein bisschen Surfen. Website da, Website dort- leichte Darstellungsprobleme, kein Silverlight. (was hat der Manager geraucht, der entschieden hat Flash für ARM zu delivern, aber kein Silverlight). Word ausprobiert. Doc aus Skydrive geladen. Alles gut. Just Working.

Dann kam der Zeitpunkt des Vermissens. Aufgrund schwerer persönlicher Störungen zwischen der Windows Suche und mir, haben wir uns im gegenseitigen Einvernehmen vor Jahren getrennt. Neuer Partner Agent Ransack. Volltextsuche auf SSD macht Laune. Aber nicht auf ARM. Visual Studio natürlich auch nicht.

Also Tablet auf die Seite gelegt,  T900 aufgemacht, durchgeatmet und zuhause gefühlt.

[Update]das Keyboard ist heute gekommen ( in weiß). Cooles innovatives Teil. Und heute Abend werde ich einmal Remote Debugging probieren. [/UPDATE]

[Disclamer]

Ich weis das unheimlich viele Leute meine Blogs und Facebook Einträge lesen und dies nicht kommentieren. Es ist ein Zeichen persönlicher Wertschätzung. Ich schätze es sehr, wenn Du lieber Leser auf einem der beiden Kanäle dazu beitragen.

[/Disclamer]

[Loveletter]

Ich bin ein Fan von Microsoft, noch immer. Man sieht, sie lernen. Windows 8 macht Sinn und ist in weiten Teilen sehr gut geworden. Touch macht Sinn. Das Surface (wie so gut wie jedes Stück Micrsoft Hardware): Gratulation gelungen.

[/Loveletter]

Windows Forms Call WinRT

Vor längerer Zeit hat Holger Schwichtenberg schon einmal das Thema aufgegriffen und gestern Scott Hanselman in seinem Blog. Wie kann man Funktionen von Windows 8 in Windows Forms (oder WPF etc.) nutzen. Ganz konkret API calls aus WInRT. Das ist eigentlich von Microsoft nicht vorgesehen und deshalb mit Vorsicht zu genießen.

In diesem VB.NET Beispiel wird der Lichtsensor angesprochen. Das kann man seit Windows 7 über die location und Sensor API tun. Es gibt sogar eine passende Erweiterung für Silverlight die native Extensions.

Trotz all dem soll die Einbindung von Winrt in Windows Forms mit Visual Basic demonstriert werden. Um eine Referenz erstellen zu können muss in vbproj File eine Ergänzung vorgenommen werden.

  <PropertyGroup>
   ...
    <TargetPlatformVersion>8.0</TargetPlatformVersion>
  </PropertyGroup>

Wenn man nun den Lichtsensor anspricht, weist einen Visual Studio Intellisense darauf hin, das die Referenzen fehlen.

image

Es muss natürlich noch die Reference auf die WinRT API erstellt werden.

image

Nun kann ein Objekt für das Sensor Handling instanziiert werden.

Public Class Form1
    Dim light As LightSensor = LightSensor.GetDefault()

Als nächstes wird auf die Änderungen des Sensors reagiert und das passende Event registriert.

 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        If light IsNot Nothing Then
            Dim minReportInterval As UInteger = light.MinimumReportInterval
            Dim reportInterval As UInteger = If(minReportInterval > 16, minReportInterval, 16)
            light.ReportInterval = reportInterval
            AddHandler light.ReadingChanged, AddressOf licht
        End If

 End Sub

Nun kann man zur Ausgabe der Daten im UI schreiten. Da WinRT typisch die Helligkeitswerte nicht im UI Thread kommen, per Invoke die Daten mit der UI synchronisiert. Die Klasse Dispatcher ist in Winforms nicht vorhanden.

Private Sub licht(sender As Object, e As LightSensorReadingChangedEventArgs)
     Me.Invoke(Sub() Label1.Text = e.Reading.IlluminanceInLux)
End Sub

Dont make me think. Textbox Eingaben Filtern

Üblicherweise kennt man seine Pappenheimer. Im Falle von Windows 8 Store APPs, kennt man sie aber nicht. Nicht mal den Tester kennt man, geschweige denn könnte man nachfragen oder ihn gar anrufen.

Die Aufgabe die ein Benutzer bekommt. Schreibe hier deinen Server Namen hin. Ergebnis bisher:

  • http://Server.de
  • //server.de
  • https://server.de
  • //server

Natürlich könnte man episch den Windows Dialog füllen mit umfangreichen beschreibenden Hinweisen. Ich bin allerdings der Meinung das “Server Name” reichen muss. Kürzere Texte lassen sich schneller lesen. Darüber hinaus liest doch ohnehin keiner mehr was. Oder man baut umfangreiche Logik, die die Daten sozusagen normalisiert.

Besser wäre es, wenn der Benutzer genau weis, was da rein gehört, bzw. einen eindeutigen Hinweis erhält wenn es nicht stimmt. Ich habe schon beschrieben, das eine Fehlermeldung direkt über der Textbox das beste Feedback an den User gibt.

Jetzt stellt sich die Frage, wie filtert man die Tastatureingaben in der Textbox?

Es gibt jedenfalls keine Möglichkeit, direkt z.B. mit regular Expressions Tastaturcodes zu filtern. Es gibt auch kein FilteredTextbox Steuerelement direkt von Microsoft.

Der nächste Ansatz lässt einen das Keydown Event der Textbox vermuten, wie folgender einfacher VB.NET Code zeigt.

Private Sub text1_KeyDown_1(sender As Object, e As KeyRoutedEventArgs)
        output1.Text = e.Key.ToString + "-" + e.KeyStatus.ScanCode.ToString
 End Sub

Allerdings sind das wirklich die Keys. Also sowohl Doppelpunkt : als auch Punkt . liefern auf einer deutschen (und nur dort) den gleichen Code, nämlich 190. Manche Szenarien, wie die Beschränkung auf numerische Eingaben lassen sich in der Tat so lösen. Einfach nur im Filterfall e.handled=true und schon verschwindet das Zeichen. (Scancode ist 52 und ebenfalls ident).

Man kann allerdings die Zeichen auslesen mit dem CharacterReceived Event. Das ist einigermaßen kompliziert über Umwege in .NET WinRT zu erreichen. Im folgenden VB Beispiel ergibt sich so für den : 58 und für den . 46.

Private Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Dim c As CoreWindow = CoreWindow.GetForCurrentThread
        AddHandler c.CharacterReceived, AddressOf somenewkeyarrived
End Sub

Private Sub somenewkeyarrived(sender As CoreWindow, args As CharacterReceivedEventArgs)
        output1.Text = args.KeyCode
        args.Handled = True
End Sub

Leider hilft uns das kaum weiter. Wir wissen zwar das böse / oder : gekommen sind, aber was tun?

Kommen wir zum Dritten Ansatz, das Event TextChanged. Hier wird einfach der gesuchte Character per Replace wieder ersetzt. Allerdings steht dann der Cursor in der Textbox am Anfang und muss mit zwei Zeilen wieder in die vorige Position gesetzt werden.

Private Sub text1_TextChanged_1(sender As Object, e As TextChangedEventArgs)
        If sender.text.contains(":") Then
            output1.Text = sender.text
            Dim i = sender.selectionstart
            sender.text = sender.text.replace(":", "")
            sender.selectionstart = i - 1
        End If
End Sub

Das funktioniert zwar, benötigt aber eine Menge Code im User Interface. Wünschenswert wäre ein XAML Attribut ala FilterCharacters.

Wenn man sich mit MVVM beschäftigt, bleibt ohnehin nur das Event Lostfocus. Erst danach wird ein gebundenes Datenobjekt aktualisiert und kann auf Gültigkeit überprüft werden. Einen UpdateSourceTrigger wie in WPF gibt es jedenfalls auch nicht in WinRT XAML.

ASMX Service unter Windows 8 Store APP nutzen

Die guten alten ASP.net Web Services sollten eigentlich schon seit .net knapp 10 Jahren durch WCF abgelöst werden. Aber ASMX findet sich auch heute noch, teilweise auch neu implementiert in vielen Software Projekten. Es ist einfach zu programmieren, zu hosten und zu troubleshooten. Selbst SharePoint bietet eine Reihe von Schnittstellen als ASP.NET Web Service an.

Als Basis dient folgender sehr einfacher ASMX Service, der in einem eigene Projekt innerhalb der Windows 8 Store APP Visual Studio 2012 Solution angelegt wird (vormals METRO).

Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel

System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class WebService1
    Inherits System.Web.Services.WebService

    <WebMethod()> _
    Public Function GetKunden() As List(Of kunde)
        Dim l As New List(Of kunde)
        l.Add(New kunde With {.ID = "1", .isMale = True, .FamName = "Mayer", .Vorname = "Klaus"})
        l.Add(New kunde With {.ID = "9", .isMale = False, .FamName = "Becker", .Vorname = "Verona"})
        l.Add(New kunde With {.ID = "13", .isMale = True, .FamName = "Weber", .Vorname = "Gerhard"})
        l.Add(New kunde With {.ID = "31", .isMale = True, .FamName = "Müller", .Vorname = "Thorsten"})
        Return l
    End Function

End Class
Public Class kunde
    Property ID As String
    Property Vorname As String
    Property FamName As String
    Property isMale As Boolean
End Class

Um diesen Service zu nutzen erzeugen die meisten im Visual Studio Projekt per Add Service Reference und URL des Services die Proxy Klassen im Projekt. In einer Winforms Anwendung (nach wie vor) kann man das mehr oder minder direkt über den Zusatzdialog “Advanced” tun.

image

Diese Option fehlt bei Windows 8 Apps, schlicht weil es dort kein .net 2.0 mehr gibt.

Auf den ersten Blick ist das auch nicht nötig, weil man das auch direkt ganz gut hinbekommt.

image

Allerdings muss im Gegensatz zu Windows Forms in der WinRT, die Kommunikation Asynchron abgehandelt werden. Das erzeugt ganz neue Problemstellungen für den .NET Code bzw. der VB.NET Source kann nicht direkt wieder verwendet werden.

 Dim svc As New ServiceReference1.WebService1SoapClient
    Private Async Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Dim resp = Await svc.GetKundenAsync()
        liste1.ItemsSource = resp.Body.GetKundenResult
 End Sub

Der nötige XAML Code mit einem Listeview Steuerelement in der Page

<ListView x:Name="liste1">
    <ListView.ItemTemplate>
       <DataTemplate>
          <StackPanel Orientation="Horizontal">
              <TextBlock Text="{Binding VorName}"  Padding="0,0,5,0"/>
              <TextBlock Text="{Binding FamName}" FontWeight="Bold" />
          </StackPanel>
        </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

Letztendlich die Ausgabe der Windows 8 APP

image

Noch ein Paar Hintergrund Infos. Da Windows 8 .NET 4.5 verwendet, kommen eigentlich WCF Proxys zum Einsatz. Microsoft hat allerdings im WCF Bereich ob des konfigurations Desasters auf die App.Config verzichtet. Statt “Contract First” lautet nun die Devise Konvention über Konfiguration.

Also wo findet man nun die nötigen Parameter. Im Code- der reference.vb.

image

Den kann man natürlich ändern, muss aber in Kauf nehmen, das wenn die Service Reference aktualisiert wird, die Änderungen weg sind.

Eingabefehler abfangen in Windows 8 Store APP’s

Anders als in WPF oder Silverlight, hat das XAML UI Framework von WInRT keine Templates oder Mechanismen um Fehler an den Benutzer zu melden oder ihn zu leiten. Also ist in WinRT Handarbeit angesagt für das Errorhandling.

Optisch erscheint es sinnvoll, über eine Textbox einen rot eingefärbten Textblock zu platzieren, die über das Visbility Attribut gesteuert wird. Um es einheitlich im Layout handhaben zu können, bietet sich eine Gruppierung mit Stackpanel an.

image

Nun stellt sich díe Frage, wie man die Logik unterbringt. VB.NET Entwickler werden aus jahrelanger Erfahrung gerne zum lostfocus Event greifen.

Das Problem ist, das man auch das Event GotFocus nutzen muss, um die Fehlermeldung wieder auszublenden, wenn der Benutzer den Cursor in die Textbox zurück setzt. Folgender VB.NET Code prüft auf ein X und meldet dann einen Fehler.

 Private Sub TextBox_LostFocus_1(sender As Object, e As RoutedEventArgs)
        If sender.text.contains("x") Then
            errorTextbox1.Visibility = Windows.UI.Xaml.Visibility.Visible
        End If
 End Sub

 Private Sub TextBox_GotFocus_1(sender As Object, e As RoutedEventArgs)
        errorTextbox1.Visibility = Windows.UI.Xaml.Visibility.Collapsed
 End Sub

Der Code sieht etwas seltsam aus (wo ist der Typcast) funktioniert aber so unter Windows 8.

Wenn man allerdings Databinding verwendet, ergeben sich neue Problemstellungen. Ich setze hier eine Klasse class1 mit einem Property prop vom Typ String.

 <TextBlock Foreground="Red" Text="Bitte die Eingabe überprüfen" Visibility="Collapsed"
x:Name="errorTextbox1"></TextBlock> <TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding prop,Mode=TwoWay}"
GotFocus="TextBox_GotFocus_1" LostFocus="TextBox_LostFocus_1" VerticalAlignment="Top"/>

Die Zuweisung der Datenquelle erfolgt über den DataContext

Private Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Dim c As New Class1
        c.prop = "test"
        Me.DataContext = c
 End Sub

Um auf den Inhalt des Datacontext zugreifen zu können, wird man unter Umständen, die vorige Codezeile einfach umdrehen. Das klappt aber in Lostfocus nicht, bzw liefert den letzten Inhalt der Textbox und nicht den aktuellen.

Also folgender Code erzeugt ein falsches seltsames verzögertes Verhalten.

 Private Sub TextBox_LostFocus_1(sender As Object, e As RoutedEventArgs)
        If Me.DataContext.prop.Contains("x") Then
            errorTextbox1.Visibility = Windows.UI.Xaml.Visibility.Visible
        End If
 End Sub

In WPF lässt sich das mit der BindingExpression und UpdateSource umgehen. Ich habe aber keine WinRT .NET Entsprechung gefunden.

Ist auch nicht essentiell, da es wahrscheinlich sinniger ist, die mit zwei Events nötige komplexe Logik in die Hände des Class1 Objektes zu geben. Diese bekommt dazu eine Eigenschaft isValid, die dann folgend an die ErrorTextbox gebunden wird. Da allerdings die Textbox zwar in das Objekt schreiben kann, aber nichts davon mitbekommt, wenn sich der Inhalt des isValid Propertys nachträglich ändert, muss diese davon unterrichtet werden. Das wird über ein Nachrichtensystem implementiert, das das Interface InotifyPropertyChanged mitliefert. Wenn sich isValid verändert wird dann per Code das Event erzwungen (raisevent).

Ergänzend: in .NET 4.5 gibt es nun einen Methode CallMemberName, die etwas weniger Code benötigt.

Public Class Class1
    Implements INotifyPropertyChanged

    Private _prop1 As String
    Public Property prop() As String
        Get
            Return _prop1
        End Get
        Set(ByVal value As String)
            If value.Contains("x") Then
                isValid = Visibility.Visible
            Else
                _prop1 = value
                isValid = Visibility.Collapsed
            End If

        End Set
    End Property
    Private _isValid As Windows.UI.Xaml.Visibility
    Public Property isValid() As Windows.UI.Xaml.Visibility
        Get
            Return _isValid
        End Get
        Set(ByVal value As Windows.UI.Xaml.Visibility)
            _isValid = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("isValid"))
        End Set
    End Property

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) 
Implements INotifyPropertyChanged.PropertyChanged End Class

Über die Implementierung von Überprüfungslogik kann man trefflich diskutieren. Wahrscheinlich wird man in der Praxis noch ein Fehlerobjekt mit Details mitführen. In Silverlight musste man z.B. Exceptions auslösen. Wie man sehen kann, hat man nun nur mehr Code an einer Stelle (im Datenobjekt) und keinen Code mehr in der Seite (im View). Richtig, das deckt sich mit dem Design Pattern MVVM.

Die Bindung in XAML ist nun ein leichtes und beinhaltet keine Überraschungen.

<StackPanel>
   <TextBlock Foreground="Red" Text="Bitte die Eingabe überprüfen" Visibility="{Binding isValid}" 
/> <TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding prop,Mode=TwoWay}"

Als Steigerungsstufe (ab hier optionales weiterlesen) wird auch noch der Code aus dem Load Event des Views eliminiert. Auch das geht per Binding im XAML.

<Page.Resources>
       <local:Class1 x:Key="class1"/>
</Page.Resources>
<StackPanel DataContext="{StaticResource class1}"

Passwort aus Setting sicher speichern in Windows 8

Ich bin ein wenig verwundert wie wenig über das Thema Credentials lokal und sicher speichern geschrieben wird. Immerhin wird so gut wie jede Windows 8 Store APP auf eine Service zugreifen und die meisten werden das auch per Autorisierung absichern.

WinRT bietet eine API um auf den Betriebssystem eigenen Passwort Tresor zuzugreifen. Dort werden auch unter anderem die Usernamen/Passwort Kombinationen aus dem Internet Explorer abgelegt.

image

Für .NET hat Microsoft eine Klasse Passwortvault, die die WinRT API nutzt spendiert. (war auch ne Prüfungsfrage beim MCP)

Dim vault As Windows.Security.Credentials.PasswordVault = 
New Windows.Security.Credentials.PasswordVault() Dim pc = New PasswordCredential("aaaaaaa", Me.DataContext.username, Me.DataContext.Passwort) vault.Add(pc)

image

Die Daten sollen dann sicher abgelegt sein und können nur aus der ursprünglichen Anwendung ausgelesen werden. Der Zugriff erfolgt über den Resource Key. Meist ist das eine URL, hier einfach aaaaaaa. Da es mehr als eine Anmeldung pro URI geben kann, kommt da ne Liste. Wenn man die Zeile mit RetrievePasswort weglässt, ist in cred der Username gesetzt, aber das Password mit einem Leerstring besetzt.

Dim vault As Windows.Security.Credentials.PasswordVault = 
New Windows.Security.Credentials.PasswordVault() Dim x = New internalSettings Try Dim cred = vault.FindAllByResource("aaaaaaa").FirstOrDefault cred.RetrievePassword() x.Passwort = cred.Password x.UserName = cred.UserName catch End Try

Der managed Wrapper scheint etwas unfertig. Es ist nicht möglich auf die Existenz eines Resource Keys zu prüfen. Hier muss man über eine Exception gehen. Außerdem gibt es eine Properties Collection zu der man per Add etwas hinzufügen kann. Zur Laufzeit krachts dann aber. 

 Dim pc = New PasswordCredential("aaaaaaa", Me.DataContext.username, Me.DataContext.Passwort)
 pc.Properties.Add("ServiceUri", Me.DataContext.ServiceUri)
        

Windows 8 Settings Charme

Ich habe bereits vor einiger Zeit einen kritischen Blog Beitrag verfasst, wie man nach den Windows 8 Store APP Richtlinien Einstellungen in Anwendungen realisiert. Tim Heuer hat vor einiger Zeit ein kleines Projekt gestartet (Callisto), das es leichter machen soll u.a. auch einen Setting samt Flyout zu realisieren. Die Grundidee gleicht dem Silverlight Toolkit. Der Sourcecode ist auf Github zu haben.

Da ich eigentlich weniger Arbeit haben will und nicht mehr, nehme ich das Paket von Nuget. Das ist zwar nicht ganz aktuell, aber ich habe nicht vor Bugfixes an Open Source vorzunehmen.

image

Um der WinRT App mitzuteilen, das der Benutzer das Setting Charme geöffnet hat, muss ein Event abonniert werden. Ein guter Ort dafür ist die App.xaml.vb  (Für C# Developer weniger gut Winking smile) und dort am Ende des OnLaunched Events.

  AddHandler SettingsPane.GetForCurrentView().CommandsRequested, AddressOf OnSettingsRequest

Im SettingsRequest wird dann ein Menüpunkt eingefügt.

  Protected Sub OnSettingsRequest(sender As SettingsPane, args As SettingsPaneCommandsRequestedEventArgs)
        Dim h As New SettingsCommand("SpListe", "Config", 
New UICommandInvokedHandler(AddressOf SettingsFunktion)) args.Request.ApplicationCommands.Add(h) End Sub

Erst wenn der Benutzer diesen auswählt wird dann das Settingspane geöffnet und der neue Punkt Config eingefügt.

image

 

Erst ab hier kommt die Callisto Bibliothek zum Einsatz.

Private Sub SettingsFunktion()
        Dim s = New SettingsFlyout()
        s.Content = New settings1
        s.HeaderBrush = New SolidColorBrush(Colors.DarkBlue)
        s.Background = New SolidColorBrush(Colors.White)
        s.HeaderText = "Config …."
        s.IsOpen = True
 End Sub

Der Eigentliche Dialog ist ein XAML Usercontrol mit dem Namen settings1.xaml.

image

Sharepoint 2010 und Windows 8 Store App

Ich weis noch immer nicht, wie die Windows METRO Anwendungen nun heißen. Kein gutes Zeichen fürs Marketing. In Visual Studio heißt das Template Windows Store, was nicht ganz richtig ist, weil man wohl auch Desktop Anwendungen … lassen wir das.

Im Rahmen einer Machbarkeitsstudie werden Interfaces von SharePoint evaluiert um sie in WinRT zu verwenden. Aktuell wird auf die SharePoint REST Services programmiert. Weil ich faul bin über einen Proxy in Visual Studio 2012.

Entsprechend der Odata Query Language wartet dort ein WCF Service, der sich an den ADO.NET Dataservices anlehnt. URL ist https://server/_vti_bin/ListData.svc/

sharepointservice

In meinem Fall musste ich drei mal meine Domain Account eingeben um die Referenz erstellt zu bekommen.

Mit Hilfe des Proxy lässt sich dann der Data Service instanziieren. Der Name IntranetDataContext ergibt sich in diesem Fall aus dem verwendeten SharePoint.

 Dim dc As IntranetDataContext = 
New IntranetDataContext(New Uri("https://server/_vti_bin/ListData.svc"))

Wenn die Namen unklar sind einfach im Class View von Visual Studio nach DataContext suchen.

Als nächstes geht es um die Authentifizierung am Sharepoint

 Dim cr = New System.Net.NetworkCredential("usr", "pwd", "domain")
 dc.Credentials = cr

Dann wird der Service aufgerufen. Weil dieser den ASYNC Pattern aus .NET 4.5 nicht implementiert auf die gute alte Beginexecute und Endexcute Methode um asynchron zu bleiben. Die Liste heist Mitarbeiter und kann auch direkt im Browser per https://server/_vti_bin/ListData.svc/Mitarbeiter so abgerufen werden.

 dc.BeginExecute(Of MitarbeiterItem)(New Uri("Mitarbeiter", UriKind.Relative), AddressOf fertig, dc)

Am Schluss dann noch die Rückrufmethode die den Aufruf abschließt und die Daten erhält aber dummerweise in einem anderen Thread aufgerufen wird. Also muss man noch den Dispatcher bemühen.

Public Async Function fertig(ByVal result As IAsyncResult) As Task
        Dim data = dc.EndExecute(Of ServiceReference1.MitarbeiterItem)(result).ToList

        Await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub()
                                                                     listbox1.ItemsSource = data
                                                                 End Sub)
 End Function
Jump Start Training: JavaScript, HTML und CSS

Month List