Kolumne: Silverlight Expertise

Browserfenster schließen LINQ to VisualTree Tonaufnahmen mit Windows Phone 7
Kommentare

Die Silverlight-Kolumne „Silverlight Expertise“ präsentiert monatlich zwei leckere Top-how-tos zum Thema Silverlight, sodass Einsteiger und fortgeschrittene Silverlight-Experten durch geballtes Wissen gesättigt werden. Heute stehen auf der Menükarte „Browserfenster schließen“, „LINQ to VisualTree“ und „Tonaufnahmen mit Windows Phone 7“. Viel Spaß und einen guten Appetit!

Menü 1 für Einsteiger: Browserfenster schließen

Eine Silverlight-Anwendung kann nur out of Browser selbstständig geschlossen werden. Um dennoch diese Anforderung auch innerhalb des Browsers nutzen zu können, muss man sich mit JavaScript behelfen. In Silverlight wird JavaScript mittels HtmlPage.Window.Invoke() ausgeführt. Um nun das aktuelle Browserfenster zu schließen, wird nur der JavaScript-Befehl close benötigt. Somit schließt folgender Code das aktuelle Browserfenster: System.Windows.Browser.HtmlPage.Window.Invoke(„close“);.

Menü 2 für Experten: LINQ to VisualTree

Das besondere an XAML ist die einfache Verschachtelung unterschiedlicher UIElements. Das befördert einiges an Gestaltungsfreiheit für das Oberflächendesign. Am Ende ergibt das eine Hierarchie von UIElementen, die als VisualTree bezeichnet wird. Beim Programmieren eigener User Controls wird oft ein Zugriff auf bestimmte UIElemente benötigt. Der Zugriff kann jetzt durch zwei Möglichkeiten stattfinden: entweder explizit durch das Zuweisen eines Namens, worauf dann im Code zugegriffen werden kann, oder man hangelt sich durch den VisualTree und filtert sich somit UIElement raus. Die erste Variante funktioniert bei statischen Aktionen sehr gut, solange man direkten Zugriff auf das XAML hat. Die zweite Lösung ist etwas aufwändiger und verbraucht mehr Zeit. Als Abhilfe dafür dient das Schreiben eines eigenen LINQ-to-VisualTree-Providers.

Für den LINQ-to-VisualTree-Provider wird eine neue statische Klasse namens LinqToVisualTree angelegt. Sie bekommt dann eine statische GetVisualTree-Methode. Der Rückgabetyp soll ein IEnumberable werden. Denn LINQ to Objects unterstützt das IEnumberable, womit unsere Ergebnisse automatisch auch mit LINQ behandelt werden können. Welcher Typ von UIElement gewollt ist, wird mittels Generics definiert. Das Root-Element wird dann mittels Parameter der GetVisualTree-Methode überreicht.

Wird das Root-Element (vom Typ DependencyObject) eingereicht, wird erst überprüft, ob sein Zustand nicht Null ist. Anschließend wird mit der statischen Klasse VisualTreeHelper und der GetChildrenCount-Methode die Anzahl der Kinderelemente vom Root-Element abgefragt. Daraufhin soll in einer For-Schleife jedes Kinderelement explizit genommen werden. Um jetzt eine Rekursion zu unterstützen, wird einfach eine weitere Foreach-Schleife auf dessen Kinderelemente durchlaufen. Dabei wird unser eigener LINQ-to-VisualTree-Provider beansprucht. Wenn er wiederholt aufgerufen wird und sein Root-Element genau dem gesuchten Element entspricht, soll es sofort zurückgegeben werden. Den Sourcecode zum eigenen LINQ-to-VisualTree-Provider finden Sie in Listing 1.

Listing 1: LINQ-to-VisualTree-Provider

public static class LinqToVisualTree
{
   public static IEnumerable GetVisualTree(DependencyObject dependencyObject) where T : UIElement
   {
       if (dependencyObject is T)
       {
           yield return dependencyObject as T;
       }

       if (dependencyObject != null)
       {
           int childrensCount = VisualTreeHelper.GetChildrenCount(dependencyObject);

           for (int i = 0; i < childrensCount; i++)
           {
               foreach (var childElement in GetVisualTree(VisualTreeHelper.GetChild(dependencyObject, i)))
               {
                   yield return childElement;
               }
           }
       }
   }
}  

Als Abfragebeispiel wird auf der MainPage.xaml ein StackPanel mit einer TextBox und einem Button angelegt. Wird auf den Button geklickt, sollen vom allgemeinen Root-Element (Application.Current.VisualRoot) alle Kinderelemente nach der TextBox durchforstet werden. Ist die TextBox gefunden worden, soll mittels Where-Abfrage sichergestellt werden, ob auch ein Text vorhanden ist. Anschließend geben wir in einer MessageBox ihren Text an. Listing 2 zeigt diese Abfrage.

Listing 2: LINQ Abfrage über den VisualTree

private void Button_Click(object sender, RoutedEventArgs e)
{
    var message = (from element in LinqToVisualTree.GetVisualTree(Application.Current.RootVisual)
                               where !string.IsNullOrEmpty(element.Text)
                               select element).FirstOrDefault();

    if (message != null) 
        MessageBox.Show(message.Text);
}  
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -