Le truc à la con du jour : GridSplitter et Grid, comment sauver les tailles des colonnes?

5. janvier 2011

Alors voila le topo: j’ai une grid avec des splitters dedans pour changer la taille des colonnes:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition MinWidth="200" Name="column0"/>
        <ColumnDefinition MinWidth="200" Name="column1"/>
        <ColumnDefinition MinWidth="200" Name="column2"/>
    </Grid.ColumnDefinitions>
    <Rectangle Grid.Column="0" Fill="Red"/>
    <Rectangle Grid.Column="1" Fill="Blue"/>
    <Rectangle Grid.Column="2" Fill="Green"/>
    <GridSplitter Grid.Column="0" VerticalAlignment="Stretch" 
HorizontalAlignment="Right" Width="4"/> <GridSplitter Grid.Column="1" VerticalAlignment="Stretch"
HorizontalAlignment="Right" Width="4"/> </Grid>

Je voudrais à la fermeture sauver la taille de mes colonnes et pouvoir les refixer lors du chargement suivant.

Du coup, bêtement, lors du chargement je faisais ça:

column0.SetValue(ColumnDefinition.WidthProperty, new GridLength(300));
column1.SetValue(ColumnDefinition.WidthProperty, new GridLength(300));
column2.SetValue(ColumnDefinition.WidthProperty, new GridLength(300));

Et bien je vous le donne en mille : ça ne marche pas! En effet, lorsque je bouge par la suite mes colonnes, la taille des colonnes semblent vouloir rester constante et le comportement global est inadapté.

La solution, comme toujours, est simple. En effet, les colonnes ont une propriété Width (et Height) qui n’est pas qu’un double mais un objet de type GridLength. Or ce dernier permet d’exprimer des tailles absolues (comme ci-dessus) mais aussi des tailles relatives (le célèbre “300*”).

Ainsi, pour conserver le comportement des colonnes tout en remettant les tailles de départ correctement il suffisait d’exprimer les tailles en relatif:

column0.SetValue(ColumnDefinition.WidthProperty, new GridLength(300, 
GridUnitType.Star)); column1.SetValue(ColumnDefinition.WidthProperty, new GridLength(300,
GridUnitType.Star)); column2.SetValue(ColumnDefinition.WidthProperty, new GridLength(300,
GridUnitType.Star));

WPF

Le truc à la con du jour : Lancement de plusieurs fenêtres en série dans WPF

4. juin 2010

Un truc bien débile qui m’est arrivé aujourd’hui. Au sein d’une application WPF qui poutre (http://urzagatherer.codeplex.com), je voulais, lors du lancement ouvrir une première fenêtre avant la fenêtre principale.

Le code ressemble donc à ça dans le constructeur de mon App:

            InstallDatabaseWindow databaseWindow = new InstallDatabaseWindow();
            databaseWindow.ShowDialog();

            MainWindow mainWindow = new MainWindow();
            mainWindow.Show();

Rien de bien formidable me direz-vous? Et bien si vous faites un test, vous verrez que le Show sur votre mainWindow.Show() plantera généreusement avec le message suivant:

“Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.”

Bon, au premier abord, je me suis dit que j’ai du merdé dans mon constructeur.

En fait, pas du tout (je me disais aussi que ce n’était pas possible) l’explication est plus sioux : Par défaut, une application WPF possède une propriété ShutdownMode qui est par défaut réglée sur OnLastWindowClose. En gros dès qu’il n’y a plus de fenêtres en vie, l’application va se fermer gentillement.

De ce fait, dans le cas du lancement de plusieurs fenêtre en série, dès que la première se ferme, l’application vérifie sa propriété ShutdownMode et se retrouve à se fermer puisque la fenêtre suivante n’a pas encore été instanciée! Ce qui fait que lorsque l’on va faire le Show() suivant, comme l’application est en cours de fermeture, la fenêtre va recevoir un Close et donc ne pourra pas s’ouvrir puisqu’elle a déjà été fermée :)

Deux solutions:

  • Instancier ses fenêtres toutes en simultanée avant de faire apparaitre la première
  • Mettre l’application sur le mode ShutdownMode.OnExplicitShutdown et s’abonner à l’événement Closed de la dernière fenêtre pour appeler la méthode Shutdown() sur l’application

 

Et le tour est joué…

.Net, WPF