Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide
Toujours dans le même thème que mes précédents posts ( et ), je continuais mes utilisations des templates avec Silverlight. L'idée est de pouvoir créer un template modèle pour plusieurs contrôles de même type (En résumé, créer un thème).
Dans mon projet, je dispose de 5 boutons (voici un extrait de 2 boutons).

<Button Grid.Column="0"
x:Name="btnFirst"
Style="{StaticResource BtnStyle}"
Width="30"
HorizontalAlignment="Left"
Margin="0 2 0 2">
<Image Source="../Images/Controls/btnFirst.png" Height="15" Width="15" />
</Button>

<Button Grid.Column="1"
x:Name="btnFastRewind"
Style="{StaticResource BtnStyle}"
Width="30"
HorizontalAlignment="Left"
Margin="0 2 0 2">
<Image Source="../Images/Controls/btnFastRewind.png" Height="15" Width="15" />
</Button>



Voici le style que j'utilise (un peu similaire que ceux de mes précédents billets) :

<UserControl.Resources>
<vsm:Style x:Key="BtnStyle" TargetType="Button">
<vsm:Setter Property="Cursor" Value="Arrow"/>
<vsm:Setter Property="Background" Value="Transparent"/>
<vsm:Setter Property="Template">
<vsm:Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="BorderBrush" Color="#FFFFFF"/>
</Grid.Resources>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualStateGroup.Transitions>
<vsm:VisualTransition Duration="0:0:0.3" To="MouseOver"/>
</vsm:VisualStateGroup.Transitions>
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="MouseOver">
<Storyboard x:Name="MouseOverAnimation" >
<ColorAnimation
BeginTime="00:00:00"
Duration="0"
RepeatBehavior="Forever" AutoReverse="True"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
To="#444444" />
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Pressed"/>
<vsm:VisualState x:Name="Disabled"/>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>

<Rectangle x:Name="Background"
Fill="{TemplateBinding Background}"
RadiusX="4" RadiusY="4"/>
<Rectangle x:Name="BackgroundGradient"
Stroke="{StaticResource BorderBrush}"
StrokeThickness="1" RadiusX="4" RadiusY="4"/>

<ContentPresenter
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</ControlTemplate>
</vsm:Setter.Value>
</vsm:Setter>
</vsm:Style>
</UserControl.Resources>


Tout compile correctement, mais, le menu n'a pas le comportement que j'attends. En effet, avec ce code, quand on survole mes 2 premiers boutons, le changement d'état n'opère pas, puis (sous Firefox en tout cas), la couleur de Background reste active après avoir effectué un premier clic !

Après avoir posé la question sur les forums Silverlight, j'ai été éclairé sur les raisons de ce mauvais fonctionnement... Je cite :

[...] you need to set Background in your Button xaml because you rely on the TemplateBinding for the Rectangle.Fill property which can be any kind of Brush. So you'd better initialize it with Solid color Brush. Otherwise, the animation does not find the target. [...]

La solution se trouve donc dans le forum. ça me laisse cependant un peu perplexe, car j'étais pourtant sûr qu'en initialisant la propriété Fill du Rectangle (bindé à la propriété Background au début de mon style), au moins un type de Brush était initialisé... Je reviendrai cependant là dessus... (Sauf si vous avez une réponse supplémentaire :-) ).

Voilà!

A +



0 commentaire(s)
Classé sous :
Dans mon billet précédent,je rappelais un peu comment avec Silverlight on pouvait créer un bouton (Texte et Image) avec un effet de MouseOver. Ici, je vais faire juste rappeler comment créer un Contrôle qui sera facilement réutilisable (là aussi, rien de compliqué :-) ).

Pour ce faire, je créé un nouveau UserControl (en incluant son CodeBehind) TopMenuButton.xaml par exemple.

<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d"
  x:Class="MonProjet.TopMenuButton"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
  
  <UserControl.Resources>
    <vsm:Style x:Key="BtnTopMenuStyle" TargetType="Button">
     <vsm:Setter Property="Foreground" Value="#FFFFFF"/>
     <vsm:Setter Property="Cursor" Value="Arrow"/>
     <vsm:Setter Property="TextAlignment" Value="Left"/>
     <vsm:Setter Property="TextWrapping" Value="NoWrap"/>
     <vsm:Setter Property="FontSize" Value="10"/>
     <vsm:Setter Property="Template">
        <vsm:Setter.Value>
          <ControlTemplate TargetType="Button">
            <Grid>
              <Grid.Resources>
              <!-- Grid.Resources Here -->
              </Grid.Resources>
              <vsm:VisualStateManager.VisualStateGroups>
                <vsm:VisualStateGroup x:Name="CommonStates">
                  <vsm:VisualStateGroup.Transitions>
                    <vsm:VisualTransition Duration="0:0:0.3" To="MouseOver"/>
                  </vsm:VisualStateGroup.Transitions>
                  <vsm:VisualState x:Name="Normal"/>
                  <vsm:VisualState x:Name="MouseOver">
                    <Storyboard>
                    <ColorAnimation Duration="0"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
To="Black" />
                    </Storyboard>
                  </vsm:VisualState>
                                      
                </vsm:VisualStateGroup>
                  
              </vsm:VisualStateManager.VisualStateGroups>
              <Rectangle x:Name="Background" RadiusX="4" RadiusY="4" Fill="{TemplateBinding Background}"/>
              <ContentPresenter
                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                Padding="{TemplateBinding Padding}"
                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                Margin="4,5,4,4"
                Content="{TemplateBinding Content}"
                ContentTemplate="{TemplateBinding ContentTemplate}"
                TextAlignment="{TemplateBinding TextAlignment}"
                TextDecorations="{TemplateBinding TextDecorations}"
                TextWrapping="{TemplateBinding TextWrapping}"/>
            </Grid>
          </ControlTemplate>
        </vsm:Setter.Value>
      </vsm:Setter>
    </vsm:Style>
</UserControl.Resources>

<Button Background="Transparent"
x:Name="btnTopMenu"
Style="{StaticResource BtnTopMenuStyle}"
Loaded="btnTopMenu_Loaded">
   <StackPanel Orientation="Horizontal">
     <Image x:Name="imgTopMenu" Margin="0, 0, 5, 0" />
     <TextBlock x:Name="tblTopMenu" VerticalAlignment="Center" Margin="0" />
   </StackPanel>
</Button>

</UserControl>



Le bouton est rendu ici (par rapport au billet précédent) beaucoup plus générique, j'ai aussi rajouté l'évènement Loaded (j'en parlerai plus bas), et j'identifie chacun des éléments enfants de mon bouton.

Je vais créer 2 propriétés maintenant pour mon bouton. Une relative à l'Url de mon image (ImageSource), et l'autre relative au texte que je veux afficher pour le bouton (MenuText).


public String ImageSource
{
   get { return (String)GetValue(ImageSourceProperty); }
   set { SetValue(ImageSourceProperty, value); }
}

public String MenuText
{
   get { return (String)GetValue(MenuTextProperty); }
   set { SetValue(MenuTextProperty, value); }
}

public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
"ImageSource", typeof(String), typeof(TopMenuButton), new PropertyMetadata(OnImageSourceChanged));

public static readonly DependencyProperty MenuTextProperty = DependencyProperty.Register(
"MenuText", typeof(String), typeof(TopMenuButton), new PropertyMetadata(OnMenuTextChanged));


private static void OnImageSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {
   if (e.NewValue != null)
   {
     // Your code here
   }
}

private static void OnMenuTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {
   if (e.NewValue != null)
   {
     // Your code here
   }
}


L'utilisation des propriétés simples / DependencyProperty, y compris la création de propriétés, Thomas en parlait dans un de ses billets, il y a déjà bien longtemps. Nous n'y reviendrons donc pas :-).

Bien, notre gestionnaire d'évènement Loaded. Quand nos propriétés seront initialisées sur notre contrôle réutilisable, il faudra les initialiser aussi sur les contrôles enfants (le TextBlock et l'Image). C'est à dire que quand je vais mettre à jour la propriété ImageSource de mon TopMenuButton, il faudra mettre à jour la propriété Source de mon Image et etc... (Vous l'aviez déjà compris :-) ).

C'est lors de l'évènement Loaded qu'il faut donc le faire (et pas dans le constructeur de notre contrôle, car ce dernier doit d'abord être initialisé avant de pouvoir accéder aux propriétés des contrôles enfants qui le compose).

private void btnTopMenu_Loaded(object sender, RoutedEventArgs e)
{
   this.imgTopMenu.Source = ResourceHelper.GetBitmap(ImageSource);
   this.tblTopMenu.Text = MenuText;
}


ResourceHelper est une petite classe simple que j'ai trouvé et qui permet de charger à partir d'un chemin (et éventuellement du nom d'une assembly), une ressource (BitmapImage, String, Xaml, ou FontSource, etc...).

Voilà, notre contrôle est prêt. Dans ma page principale (.xaml), je rajoute à l'élement UserControl

xmlns:MonProjet="clr-namespace:MonProjet"

afin de pouvoir référencer puis utiliser mon nouveau contrôle de cette façon :

<MonProjet:TopMenuButton
x:Name="btnAddContent"
        Grid.Column="0"
        MenuText="Menu 01"
        ImageSource="Images/top_menu_01.png" />
      
      <MonProjet:TopMenuButton
x:Name="btnCreatePublicPage"
            Grid.Column="1"
            MenuText="Menu 02"
            ImageSource="Images/top_menu_02.png" />



Fin du rappel :-).

Bonne journée, et A bientôt.

0 commentaire(s)
Classé sous : ,
Un petit rappel concernant les templates et les "états" des contrôles.  J’ai voulu donc créer un bouton très simple. Il s'agit d'un contrôle Button très personnalisé (Une image à gauche, du texte à droite, pas d’arrière plan, ni de bordures sur le bouton, et un rollover changeant l'arrière-plan de notre nouveau contrôle).
Pas encore très à l’aise avec Blend, j’utilise donc son éditeur XAML donc pour écrire mes templates. Voici le code de mon bouton:

<Button Background="Transparent"
        x:Name="btnAddContent"
        Grid.Column="0"
        Style="{StaticResource BtnAddContentStyle}">
     <StackPanel Orientation="Horizontal">
         <Image Source="Images/menu_icon_01.png"
                Margin="0, 0, 5, 0" />
         <TextBlock Text="Add Content"
                    VerticalAlignment
="Center"
                    Margin="0" />
    </StackPanel>
</Button>

Mon premier réflexe (pas toujours les meilleurs) est de créer mon template comme celui ci (fonctionnel sur la Beta 1 ) :

<Style TargetType="Button" x:Key="Btn3Style4444">
  <Setter Property="FontSize" Value="10" />
  <Setter Property="Foreground" Value="White" />
  <Setter Property="Cursor" Value="Hand" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid x:Name="RootElement">
          <Rectangle x:Name="Background"
                     RadiusY="5"
                     RadiusX="5" Background>
            <Rectangle.Fill>
              <SolidColorBrush x:Name="BackgroundBrush"
                               Color
="Transparent" />
            </Rectangle.Fill>
          </Rectangle>
          <ContentPresenter
            Content="{TemplateBinding Content}"
            ContentTemplate="{TemplateBinding ContentTemplate}"
            FontSize="{TemplateBinding FontSize}"
            Foreground="{TemplateBinding Foreground}"
            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
            TextAlignment="{TemplateBinding TextAlignment}"
            TextDecorations="{TemplateBinding TextDecorations}"
            TextWrapping="{TemplateBinding TextWrapping}"
            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
          />
          <Grid.Resources>
            <Storyboard x:Key="MouseOver State">
              <ColorAnimation
                Duration="0"
                Storyboard.TargetName="BackgroundBrush"
                Storyboard.TargetProperty="Color"
                To="Black"
              />
            </Storyboard>
          </Grid.Resources>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>


Ce code qui pourtant compile sans problème ne me permettra pas de changer l’état de mon bouton. En effet, en générant un template à partir d’un contrôle existant, je me suis rappelé du Visual State Manager (je ne mets pas de lien sinon, je devrais en mettre trop ;p). Une des nouvelles fonctionnalités de Silverlight 2 Beta 2 qui permet très facilement de skinner ses contrôles.

Mon code précédent deviendra ainsi:

<vsm:Style x:Key="BtnAddContentStyle"
           TargetType
="Button">
        <vsm:Setter Property="Foreground" Value="#FFFFFF"/>
        <vsm:Setter Property="Cursor" Value="Arrow"/>
        <vsm:Setter Property="FontSize" Value="10"/>
        <vsm:Setter Property="Template">
          <vsm:Setter.Value>
            <ControlTemplate TargetType="Button">
              <Grid>
                <Grid.Resources>
                <!-- Grid.Resources Here -->
                </Grid.Resources>
                <vsm:VisualStateManager.VisualStateGroups>
                  <vsm:VisualStateGroup x:Name="CommonStates">
                    <vsm:VisualStateGroup.Transitions>
                      <vsm:VisualTransition Duration="0:0:0.3" To="MouseOver"/>
                    </vsm:VisualStateGroup.Transitions>
                    <vsm:VisualState x:Name="Normal"/>
                    <vsm:VisualState x:Name="MouseOver">
                      <Storyboard>
                      <ColorAnimation
                            Duration="0"
                            Storyboard.TargetName="Background"
                            Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
                            To="Black" />
                      </Storyboard>
                    </vsm:VisualState>
                  </vsm:VisualStateGroup>
                </vsm:VisualStateManager.VisualStateGroups>
                <Rectangle x:Name="Background"
                           RadiusX
="4"
                           RadiusY="4"
                           Fill
="{TemplateBinding Background}"/>
                <ContentPresenter
                  HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                  Padding="{TemplateBinding Padding}"
                  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                  Margin="4,5,4,4"
                  Content="{TemplateBinding Content}"
                  ContentTemplate="{TemplateBinding ContentTemplate}"
                  TextAlignment="{TemplateBinding TextAlignment}"
                  TextDecorations="{TemplateBinding TextDecorations}"
                  TextWrapping="{TemplateBinding TextWrapping}"/>
              </Grid>
            </ControlTemplate>
          </vsm:Setter.Value>
        </vsm:Setter>
      </vsm:Style>

Voilà pour le petit rappel.

Bonne soirée et bon skinning!


0 commentaire(s)
Classé sous :
De retour de vacances (enfin, presque ...), heureux et motivé comme tout, je me mets à jour côté news et installe comme tout le monde (enfin, presque) VS2008 SP1. Après 2 bonnes heures de téléchargements, je me mets à l'installer et j'ai ça :



Je regarde rapidemment donc les programmes installés, et je vois ça :



VS2008 existe bien, mais dans version anglaise (Ah, l'attention ...). Je prends le soin tout de même de désinstaller toutes les versions Express que j'avais d'installé (tiens, j'avais la version fr et en de Web Developer Express...).

Bon, je prends encore 1h30 cette fois ci pour télécharger la version anglaise !

En l'installant, j'ai ça :




... Je n'avais même pas la possibilité de choisir les composants que je désirai éventuellement pouvoir mettre à jour. Mais, c'est un SP cela dit aussi....

Je peux toujours bosser, c'est déjà l'essentiel...

Bonne journée.

A+

0 commentaire(s)
Classé sous : ,
Grâce à l'information que Thomas avait relayé il y a quelques temps, j'avais participé à cette conférence sur Silverlight animée par Christophe Lauer et Pierre Lagarde. Les vidéos, et ateliers (ceux du coach Silverlight) sont disponibles en ligne. Si vous ne connaissez pas Silverlight et que vous désirez débuter avec cette technologie, je vous le recommande vivement. Ils ont constitué un excellent point d'entrée pour moi. Smile
 
Projet Touareg (WebOS en Silverlight)
 
 
A +
1 commentaire(s)
Classé sous :
Christ Craft a pris l'initiative le 1er Juin dernier, de créer une application mobile windows par jour. Hier, il a fini la 30ième application. C'est une idée que j'ai trouvé originale, parce qu'il démontre ainsi qu'il n'est pas "si difficile" de créer des applications, surtout pour un pocket pc. Il y a un peu de tout (Applications utilisant le GPS, BlueTooth, etc...). C'est encourageant et ça donne des idées Big Smile !
 
Merci Chris.
 
Vu via Coding4Fun
Pour des raisons très pratiques en interne, nous nous sommes retrouvés à vouloir migrer l'ensemble de nos projets sous VSS vers SVN. Le processus de migration serait plus simple si nous ne voulions pas garder l'historique ainsi que les labels... Soit, en ayant un peu recherché sur google, je suis tombé sur cet outil : VSSMigrate. Il n'a pas été facile de l'utiliser, alors, je partage avec vous comment y parvenir Smile.

Quelques prérequis :

VSSMigrate a besoin d'un fichier .ini pour pouvoir parvenir à réaliser cette migration. Pour des raisons toujours pratiques, je l'ai appellé mon fichier de configuration VSSMigrate.ini.
Voici le contenu de ce fichier VSSMigrate.ini



[Settings]
VSSWIN32=C:\Progra~1\Mi53b4~1\
# VSS\Win32 directory which contains ss.exe
# J'Utilise le nom dos 8.3 car le programme n'aime pas les espaces .... (dir /x vous affiche le nom court!)

VSSDIR=\\VSSServer\VSSFolder
#VSS repository directory (contains srcsafe.ini)
#use environment variable SSDIR to set the current repository.
#PENSEZ à enregistrer la variable SSDIR dans les variables d'environnement avec la commande juste ci-dessous.
#set
SSDIR=\\VSSServer\VSSFolder\


VSSPROJ=$/YourProject/
#VSS project to start at (ie $/Product)

VSSUSER=myUserName
#User to use for VSS commands, use blank for none

VSSPASSWORD=myPassword
#password to use for VSS commands, blank is OK

SVNWIN32=C:\Progra~1\Subversion\bin
# SVN\bin directory which contains svn.exe

SVNUSER="first last"
#User to use for SVN commands, use blank for none, use quotes for two names

SVNPASSWORD=
#password to use for SVN commands, blank is OK

SVNURL=file:///C:/Repository/
#URL to use for the root of the check in

SVNPROJ=$/ProjectNameUnderSVN
#VSS project to start at (ie $/Product)

WORKDIR=c:\test
#Directory under which files and directories will be created as work progresses

DEBUG=1 #turn on debug output, blank is OK
AUTORETRY=0 #if a command fails to run, it will be run automatically 1 time before failing




Pour lancer VSSMigrate, il faut utiliser la ligne de commande VSSMigrate.exe fullPathToConfigFile

Je dis bien le chemin complet, sinon, ça ne passera pas.

Bon, après, il y a eu un "petit" souci que je n'ai pas voulu modifier dans les sources (qui sont aussi disponibles mais en C++ ;p). Pour chaque fichier récupéré depuis VSS, il faudra qu'il soit committé de nouveau vers SVN.
ça fonctionne bien, excepté qu'à certains moments, le programme prompte en nous demandant d'inscrire une nouvelle heure ...  Après avoir analysé un peu tout ça, j'ai remarqué que pour chaque fichier et version qu'il committait, il chantait la date système (en fonction de la date de version).  Il faudra donc penser aussi à la remettre comme elle était auparavant si elle s'est déréglée...


Si tout s'est bien passé, l'ensemble de vos sources sur VSS seront migrées sur votre SVN local. Je l'ai fait pour des raisons (encore) pratiques et à des buts de tests, car je ne savais pas si il y avait des chances que ça plante en cours...

Restera donc plus qu'à migrer de votre SVN local au Server SVN (tâche plus facile bien entendu Stick out tongue).

Bonne Migration et à bientôt !