Archiv der Kategorie: Tip of the day

Tip of the day – LoopingSelector

Ihr kennt wahrscheinlich alle den TimePicker bzw. DateTimePicker, welche diese sehr schön umgesetzte Auswahl der Uhrzeit bzw. des Datums haben.
So eine Auswahl wollte ich auch für eine meiner Apps haben (Zune Timer) und die Lösung dazu ist der LoopingSelector.
Das müsst ihr machen:
Zuerst müsst ihr bei den Referenzen das Phone Toolkit hinzufügen (Wenn ihr dies noch nicht installiert habt, dann mal schnell nachholen. Sind ein paar sehr gute neue Controls dabei 😉 )

Dort wählt ihr:

Dann braucht ihr noch diesen Codeausschnitt auf eurer Seite wo ihr den LoopingSelector verwenden wollt:

xmlns:primitives="clr-namespace:Microsoft.Phone.Controls.Primitives;assembly=Microsoft.Phone.Controls.Toolkit"

Jetzt könnt ihr einen LoopingSelector erzeugen, mit dem folgenden Code:

<primitives:LoopingSelector
                x:Name="TutorialLoopingselector"
                Width="100"
                ItemSize="100,100"
                Height="550"
                ItemMargin="6"
                HorizontalAlignment="Center"                >
                <primitives:LoopingSelector.ItemTemplate>
                    <DataTemplate>
                        <StackPanel
                            HorizontalAlignment="Left"
                            VerticalAlignment="Bottom"
                            Margin="6">
                            <TextBlock
                                Text="{Binding}"
                                FontSize="40"
                                FontFamily="{StaticResource PhoneFontFamilySemiBold}"
                                Margin="0,-8"/>
                        </StackPanel>
                    </DataTemplate>
                </primitives:LoopingSelector.ItemTemplate>
            </primitives:LoopingSelector>

Hier könnt ihr natürlich auch alles Individuell verändern, zu dem, was ihr gerade braucht.
Das war es auch schon fast. Es fehlt nur noch die Implementation der Datasource.
Die Datasource besteht im Grunde nur aus ein paar kleinen Funktionen. Was sie hat, ist eine Funktion um den nächsten Wert zu bekommen, sowie eine Funktion um den vorherigen Wert zu bekommen. Dann braucht sie natürlich auch noch den aktuell angewählten Wert.

Um diese Klasse dann auch wirklich als Datasource benutzen zu können, muss sie von ILoopingSelectorDataSource
Erben.
Dafür muss vorher noch:

using Microsoft.Phone.Controls.Primitives;

hinzugefügt werden.
Hier die komplette Klasse. Ich habe diese für Klasse für einen Intselector gemacht (Bsp. wäre für einen Sekundenselector). Aber man kann natürlich seine komplett eigenen Schreiben. Man könnte ja auch ein Array übergeben an die Datasource, welches irgendwelche Daten enthält und dieses damit auswählen lassen. (Wie die Darstellung davon ist, kann dann natürlich im DataTemplate festgelegt werden)
Wie ihr seht, gibt es viele Möglichkeiten für eine Datasource. Hier die wahrscheinlich am häufigsten genutzte für einen Intselector:

public class IntDatasource : ILoopingSelectorDataSource
    {
        private int _selectedItem;
        private int minValue;
        private int maxValue;
        private int increment;
        public IntDatasource()
        {
            this.MaxValue = 10;
            this.MinValue = 0;
            this.Increment = 1;
            this.SelectedItem = 0;
        }

        public int MinValue
        {
            get
            {
                return this.minValue;
            }
            set
            {
                if (value >= this.MaxValue)
                {
                    throw new ArgumentOutOfRangeException("MinValue", "MinValue cannot be equal or greater than MaxValue");
                }
                this.minValue = value;
            }
        }

        public int MaxValue
        {
            get
            {
                return this.maxValue;
            }
            set
            {
                if (value <= this.MinValue)
                {
                    throw new ArgumentOutOfRangeException("MaxValue", "MaxValue cannot be equal or lower than MinValue");
                }
                this.maxValue = value;
            }
        }

        public int Increment
        {
            get
            {
                return this.increment;
            }
            set
            {
                if (value < 1)                 {                     throw new ArgumentOutOfRangeException("Increment", "Increment cannot be less than or equal to zero");                 }                 this.increment = value;             }         }         public object GetNext(object relativeTo)         {             int nextValue = (int)relativeTo + this.Increment;             if (nextValue > this.MaxValue)
            {
                nextValue = this.MinValue;
            }
            return nextValue;
        }

        public object GetPrevious(object relativeTo)
        {
            int prevValue = (int)relativeTo - this.Increment;
            if (prevValue < this.MinValue)
            {
                prevValue = this.MaxValue;
            }
            return prevValue;
        }

        public object SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                if ((int)value != _selectedItem)
                {
                    int valueWrapper = (int)value;
                    if ((valueWrapper != _selectedItem))
                    {
                        object previousSelectedItem = _selectedItem;
                        _selectedItem = valueWrapper;
                        EventHandler handler = SelectionChanged;
                        if (null != handler)
                        {
                            handler(this, new SelectionChangedEventArgs(new object[] { previousSelectedItem }, new object[] { _selectedItem }));
                        }
                    }
                }
            }
        }

        public event EventHandler SelectionChanged;
    }

Was müsst ihr sonst noch machen. Naja, nicht viel. Jetzt fehlt nur noch die Zuweisung der Datasource zu eurem Loopingselector, typischerweise im Konstruktor der Seite auf der der Loopingselector platziert ist:

public MainPage()
        {
            InitializeComponent();
            TutorialLoopingselector.DataSource = new IntDatasource() { Increment = 2, MaxValue = 60, MinValue = 0, SelectedItem = 30 };
        }

Ich arbeite an einer Möglichkeit euch den Quelltext zur Verfügung zu stellen. Leider bittet wordpress nicht die Möglichkeit Zip Dateien anzuhängen. Ich schaue mal, ob ich eine andere Lösung finden kann.

Ich hoffe ich konnte euch hiermit einen kleinen Einblick in Loopingselectoren geben.
Hier gibt es auch noch mehr Infos:

geekchamp

Ihr habt fragen, Anregungen oder sonstige Meinungen. Immer nur her damit in den Kommentaren 😉

Tip of the day – Button wie in der ApplicationBar

Button wie in der ApplicationBar
Read this article in english
Ich wollte in meine Apps Buttons einbauen, die genau wie die in der Applicationbar aussehen.

Dafür habe eine sehr schöne Lösung über Buttonstyles gefunden:

<Style x:Key="IconButton" TargetType="Button">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
            <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
            <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
            <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
            <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
            <Setter Property="Padding" Value="10,3,10,5"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid Background="Transparent">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal"/>
                                    <VisualState x:Name="MouseOver"/>
                                    <VisualState x:Name="Pressed">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentContainer">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentContainer">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="50" Margin="{StaticResource PhoneTouchTargetOverhang}">
                                <Grid x:Name="ContentContainer" OpacityMask="{TemplateBinding Content}" Background="{TemplateBinding Foreground}"/>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Diesen Code einfach in die Pageresourcen einfügen, am Anfang der Seite oder in den globalen Appresourcen:

<phone:PhoneApplicationPage.Resources>
<!--Style hier hin-->
</phone:PhoneApplicationPage.Resources>

Nun kann der Button wie folgt in der Seite verwendet werden:

<Button Height="75" Width="75" Name="play" Style="{StaticResource IconButton}">
     <ImageBrush x:Name="PlayImage" ImageSource="ButtonIcons/appbar.transport.play.rest.png" Stretch="None"/>
</Button>

Hier bei ImageSource den Link zu eurem Icon einfügen und ihr seit fast fertig. Nur noch kontrollieren, dass die Eigenschaften so gesetzt sind:

Und zum Schluss noch das Ergebnis:

Diese Diashow benötigt JavaScript.

Tip of the day – ApplicationBar like Buttons

ApplicationBar like Buttons
Lese diesen Beitrag auf deutsch
I wanted to have buttons like you get in the applicationbar but could figure out how. At the end I found a perfect solution with buttonstyles:

<Style x:Key="IconButton" TargetType="Button">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
            <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
            <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
            <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
            <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
            <Setter Property="Padding" Value="10,3,10,5"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid Background="Transparent">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal"/>
                                    <VisualState x:Name="MouseOver"/>
                                    <VisualState x:Name="Pressed">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentContainer">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ContentContainer">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="50" Margin="{StaticResource PhoneTouchTargetOverhang}">
                                <Grid x:Name="ContentContainer" OpacityMask="{TemplateBinding Content}" Background="{TemplateBinding Foreground}"/>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

You just have to insert this style in the page resource or appresource:

<phone:PhoneApplicationPage.Resources>
<!--Style hier hin-->
</phone:PhoneApplicationPage.Resources>

Now you just have to set the style of a button to the style above and set a ImageBrush as content:

<Button Height="75" Width="75" Name="play" Style="{StaticResource IconButton}">

     <ImageBrush x:Name="PlayImage" ImageSource="ButtonIcons/appbar.transport.play.rest.png" Stretch="None"/>

</Button>

As ImageSource, you use your own link to the icon you want. Now only one thing remains making sure the Build Action and Copy to Output Directory of the icon are set correctly:

And this is how it will look like: