Archiv

Artikel Tagged ‘Controls’

Daily-Hour 39: VisualStateManager VisualTransition

10. März 2010 juergen79 Keine Kommentare

Ein Control-Element wie zB. ein Button können verschiedene Zustände ahben, die auch grafisch angzeigt werden sollten. Ein Standard-Button reagiert auf MouseOver, Normal oder Pressed. Genau jetzt kommt der VisualStateManager zu tragen, der sich im System.Windwos befindet und mit einem abkürzenden Präfix wie zB: vsm (xmlns:vsm=”clr-namespace:System.Windows;assembly=System.Windows”) eingebunden.

Jedes Control besitzt spezifische Zustände (VisualState), die wiederum Zustandsgruppen (VisualStateGroup) angehören. Wenn man diese VisualState kennt, könnnen diese via VisualStateManager definiert werden.

Ein Button enthält folgende Zustände und Gruppen:

CommonStates Normal Mauszeiger befindet sich außerhalb des Controls
CommonStates MouseOver Mauszeiger ist über dem Control
CommonStats Pressed Linke Maustaste wurde gedrückt, während der Mauszeiger über dem Control ist
CommonStates Disable Das Control wurde disabled
FocusState Unfocused Control besitzt nicht den Fokus
FocusState Focused Control besitzt den Fokus

Für den Button gibt es sechs VisualStates in zwei VisualStatesGroups. Mit dem VisualStateManager kann jedem dieser VisualStates ein StoryBoard zugewiesen werden, das eine oder mehrere Animationen enthalten können, so kann ein Zustand überblendet werden. Ein Storyboard kann wie üblich definiert werden.

Die Definition des VisualStateManager erfolgt innerhalb des Controls, wie folgt:

<vsm:VisualStateManager.VisualStateGroups>
    <vsm:VisualStateGroups>
        <vsm:VisualState x:Name=”Normal”>
             <Storyboard>
                …
             </Storyboard>
        </vsm:VisualState>
        <vsm:VisualState x:Name=”MouseOver”>
             <Storyboard>
                …
             </Storyboard>
        </vsm:VisualState>
        …
    </vsm:VisualStateGroups>
</vsm:VisualStateManager.VisualStateGroups>

Diese Deklaration ist nur beispielshaft für Normal und MouseOver und kann beliebig erweitert werden und man kann dementsprechenden die Animationen im Storyboard definieren.

VisualTransition
Man kann weitgehende Kontrolle über die ablaufenden Animationen mittels VisualTransition erlangen. Die VisualTransitions werden in der TransitionsCollection gesammelt, die ein Parameter der VisualStateGroup ist. Eine Transition ist nur innerhalb einer Gruppe möglich, da die Zustände zusammengehörig sind.

Man kann über VisualTransitions definieren:

  • von welchen in welchen Zustand die Transition erfolgen soll (From, To)
  • wie lange der Zustandsübergang dauern soll (GenerateDuration)
  • ob ein Storybord gestartet wird, wenn die Zustandsänderung eintritt (Storyboard)

So kann man die Zustandsübergang von Einem zum Anderem Zustand definieren (zB Pressed nach MouseOver in 2 Sekunden)

<vsm:VisualStateManager.VisualStateGroups>
    <vsm:VisualStateGroups>
        <vsm:VisualStateGroups.Transitions>
             <vsm:VisualTransition From=”Pressed” To=”MouseOver” GeneratedDuration=”0:0:2″/>

        </vsm:VisualStateGroups.Transitions>
        ….
    </vsm:VisualStateGroups>
</vsm:VisualStateManager.VisualStateGroups>

Aber man kann auch ein Storyboard definieren, das während der angegebenen Dauer abgespielt wird.

             <vsm:VisualTransition From=”Pressed” To=”MouseOver” GeneratedDuration=”0:0:2″>
                 <Storyboard>
 
                        <DoubleAnimation Storyboard.TargetName=”EinObjekt” Storyboard.TargetPorperty=”EineProperty”/>
                 </Storyboard>
             </vsm:VisualTransition>

Die bekannten Parameter von Storyboards und Animationen können bei VisualTransitions sowie VisualStates zum Einsatz kommen, wie zB AutoReverse und RepeatBehavior.

Daily-Hour 31: Silverlight Steuerelement Teil 6: ComboBox

20. Februar 2010 juergen79 Keine Kommentare

Die ComboBox ist eine Mischung aus ListBox und Textfeld, wobei das Textfeld einigen Einschränkungen unterworfen ist. Das Textfeld kann nicht editiert werden, man kann nur einen der auswählbaren Einträge angezeigt bekommen, sonst bleibt es leer.

Die ComboBox ist ein ItemControl und enthält daher die Eigenschaften der ItemsCollection. In XAML kann man die ComboBox so deklariert werden:

<ComboBox>
    <ComboBoxItem Content=”How I met your mother”/>
    <ComboBoxItem Content=”Two and a half men”/>
    <ComboBoxItem Content=”Big Bang Theory”/>
    <ComboBoxItem Content=”House, M.D.”/>
    <ComboBoxItem Content=”Bones”/>
</ComboBox>

Die Breite der ComboBox kann wie immer über Width bestimmt werden. Die oben angeführte Deklaration der Items kann über ein ein TextBlock mit dem gewünschten Inhalt zugewiesen werden. Das ist natürlich die bequemste Art, aber sie bietet kaum Flexibilität. Das ComboBoxItem könnte auch so deklariert werden:

<ComboBoxItem>tion
    <TextBlock>How I met your mother</TextBlock>
</ComboBoxItem>

Wie man vielleicht zu diesem Moment erkennen kann, ist das ComboBoxItem recht mächtig. Man kann anstelle des TextBlock jedes beliebige Control-Element einsetzen.

Die wichtigsten Event der ComboBox sind:

  • SelectionChanged (tritt ein, wenn der Anwender seine Auswahl trifft, also ein Element aus der Liste wählt bzw. seine Auswahl ändert)
  • DropDownOpen (tritt ein, wenn das Drop-Down-Fenster geöffnet wird)
  • DropDownClosed (tritt ein, wenn das Drop-Down-Fenster geschlossen wird)

ItemsCollection ist die Grundlage eines Item-Controls. Anstelle wie vorhin direkt in XAML aufgebaut werden oder man kann das Control-Element auch via Code befüllen.

<ComboBox x:Name=”CodeFilled” Loaded=”CodeFilled_Loaded”/>

Über das Loaded-Event wird die ComboBox schließlich befüllt.

 private void CodeFilled_Loaded(object sender, RoutedEventArgs e)
{
     CodeFilled.Items.Add(“New York”);
     CodeFilled.Items.Add(“Munich”);
     CodeFilled.Items.Add(“Vienna”);
     CodeFilled.Items.Add(“Paris”);
     CodeFilled.Items.Add(“Manchester”);
     CodeFilled.Items.Add(“Miami”);
     CodeFilled.SelectedIndex = 2;
 }

Die ItemsCollection wird dabei 6-mal mit eimen String-Eintrag befüllt. Und in der letzten Zeile wird der Eintrag mit der Indexnummer 2 (Vienna) als vorgewählten Eintrag festgelegt.

Aber hier sind noch nicht die Grenze der ItemsCollection, für eine solche Sammlung kann jedes Objekt infrage kommen, welches aus einer Collection besteht und das INotifyCollectionChanged Interface besitzt.  Eine Collection, die das Interface besitzt, bietet die Möglichkeit Änderungen einer Collection zu melden. Das ist deshalb notwendig, weil jede Änderung der Collection auch eine Änderung der ComboBox-Inhalte zu folge hat.

Die ObservableCollection-Klasse besitzt dieses Verhalten und kann damit als ItemCollection dienen. Man kann diese Collection verwenden in dem man die System.Collections.ObjectModel einbindet.

Man kann damit z.B. eine Klasse defnieren, die Books heißt und die eine Collection vom Typ Book ist. Die Klasse Books leitet sich von der Klasse ObserableCollection ab, damit man die entsprechende Schnittstelle zur Verfügung hat.

Hierfür legt man eine eigene Klasse an, die book.cs heißt und wie folgt definiert wird:

public class Book
{
    public String Titel { get; set; }
    public String Autor { get; set; }
    public String Verlag { get; set; }
}

Im XAML deklarieren wir die ComboBox und zusätzlich einen TextBlock, zur Ausgabe der Auswahl, wie folgt:

<ComboBox x:Name=”Collection” Loaded=”Collection_Loaded”/>
<TextBlock x:Name=”Display_Combo” Text=”NO” TextWrapping=”Wrap” Height=”35″ />

Die ComboBox muss jetzt mit Inhalten geladen werden:

        private void Collection_Loaded(object sender, RoutedEventArgs e)
        {
            ObservableCollection<Book> books = new ObservableCollection<Book>();

            books.Add(new Book()
            {
                Titel = “Silverlight 3: Crashkurs”,
                Autor = “Otto Fischer”,
                Verlag = “Microsoft Press”
            });
            books.Add(new Book() {
                  Titel=”Pro Silverlight 3 in C#”,
                  Autor=”Matthew MacDonald”,
                  Verlag=”Apress”});
            books.Add(new Book()
            {
                Titel = “Silverlight 3″,
                Autor = “Uwe Rozanski”,
                Verlag = “Mitp Verlag”
            });
            books.Add(new Book()
            {
                Titel = “Introducing Microsoft Silverlight 3″,
                Autor = “Laurence Moroney”,
                Verlag = “Microsoft Press”
            });
            books.Add(new Book()
            {
                Titel = “Das Affenpuzzle”,
                Autor = “David Harel”,
                Verlag = “Springer Verlag”
            });

            Collection.ItemsSource = books;
            Collection.DisplayMemberPath = “Titel”;
            Collection.SelectedIndex = 1;
            Collection.SelectionChanged += new SelectionChangedEventHandler(SelectionGeaendert);
        }

Als erstes instanzieren wir ein Object books und befüllen dies mit Informationen. Nachdem alle Objekte Buchtitel, Autor und Verlag haben, binden wir das Objekt mit der ComboBox und wählen, was angezeigt werden soll (in dem Fall der Titel).

Nach der Auswahl sollte natürlich auch was passieren, wenn ein Buchtitel gewählt wurde, dass geschieht in der letzten Zeile.

Der SelectionChanged-Event-Handler wird mit gibt schließlich den Buchtitel, Autor und Verlag  im PlugIn aus.
       
        private void SelectionGeaendert(object sender, SelectionChangedEventArgs e)
        {
            ComboBox cb = (ComboBox)sender;
            ItemCollection it = cb.Items;
            Book book = (Book)it[cb.SelectedIndex];
            Display_Combo.Text = book.Titel + “, ” + book.Autor + “, ” + book.Verlag;
        }

Hier wird im ersten Schritt wieder der sender gecastet, schließlich greift man auf die ItemCollection zu und wählt ein bestimmtes Item daraus aus. Da die Collection vom Typ Book ist, kann man auf Book casten und dies der lokalen Variable zuweisen.  Durch die Auswahl des Users wird der erhält man den zugehörigen Index über den Parameter SelectedIndex der ComboBox. Und über TextBlock werden alle Elemente des Buchobjekts ausgegeben.

In der Abbildung sieht man das Ergebnis, 3 Variante wie man eine ComboBox definieren kann.

In den o.a. Beispielen wurde aber nur einmal eine Ausgabe definiert.