WPF, Xaml et Binding

Bonjour la zone,

je me remets tripoter WPF et j’avais quelques questions sur le sujet :

  • Tout d’abord il y a manifestement quelquechose que je n’ai pas saisi avec le binding :

j’ai un objet avec une liste de “points”. J’aimerai bien les “dessiner” dans un layout mais allons-y par étape. Tout d’abord je voulais binder une listbox sur la collection de mon objet. J’ai procédé comme suit :

<ListBox ItemsSource="{Binding Path=Shapes}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="X : "/> <TextBlock Text="{Binding Path=X}" /> <TextBlock Text=", Y : "/> <TextBlock Text="{Binding Path=Y}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>

là j’obtiens bien ce que je veux, c’est à dire :

Je veux ajouter également une listbox avec la même liste de points mais, convertis (via un converter) et là, ça pose problème :
voilà le converter :

[code] public class CoordinateConverter : IValueConverter
{
#region IValueConverter Members

	public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
		MyPoint myPoint = (myPoint)value;

		Point p = new Point(System.Convert.ToDouble(myPoint.X), System.Convert.ToDouble(myPoint.Y));

	// Matrice en dur, pour tests
		Matrix m = new Matrix(0.0004185596, 0, 0, -0.000418559619, -2.35983944, 1148.95776);
		MatrixTransform mt = new MatrixTransform(m);
		return mt.Transform(p);
	}


	public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
		throw new NotImplementedException();	
	}
}[/code]

Là ça fonctionne toujours avec ce code :

<ListBox Name="listBox1" ItemsSource="{Binding Path=Shapes}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Converter={StaticResource myConverter}}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox>

j’obtiens :

Par contre si je veux faire un formattage comme ma première liste (X : val , Y : val) je fais ça

<ListBox ItemsSource="{Binding Path=Shapes}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="X : "/> <TextBlock Text="{Binding Path=X, Converter={StaticResource myConverter}}" /> <TextBlock Text=", Y : "/> <TextBlock Text="{Binding Path=Y, Converter={StaticResource myConverter}}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>

Mais là ça ne fonctionne pas car ce n’est plus un MyPoint qui est passé à mon Converter mais un double (à cause du Path=X j’imagine) et forcément il lève une exception !

Mon deuxième souçi (et non des moindre) c’est que je voudrai restituer mes points sur un layout de façon “dynamique”.

Je m’explique : Je souhaiterai générer une matrix transform en fonction de la largeur et de la hauteur du layout dans lequel je souhaite afficher mes points (j’espère être clair).
Mais quand j’essaie d’obtenir la hauteur et la largeur du layout conteneur, j’obtiens un NaN… Donc je suppose qu’il faut remonter mon arbre pour trouver un conteneur qui contient une largeur et une hauteur non ? et la question est : Comment faire ?

Merci

Ok, je dois pas avoir bien compris le pb, parce que la solution me parait assez simple pour gérer les deux cas :

[code] public class CoordinateConverter : IValueConverter
{
#region IValueConverter Members

	public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
											if(value is MyPoint)
											{
		MyPoint myPoint = (myPoint)value;

		Point p = new Point(System.Convert.ToDouble(myPoint.X), System.Convert.ToDouble(myPoint.Y));

	// Matrice en dur, pour tests
		Matrix m = new Matrix(0.0004185596, 0, 0, -0.000418559619, -2.35983944, 1148.95776);
		MatrixTransform mt = new MatrixTransform(m);
		return mt.Transform(p);
											}
												
											if(value is double)
											{
														return (double)value;
											 }

											throw new NotSupportedException("blah blah");
	}


	public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
		throw new NotImplementedException();	
	}
}[/code]

Pour ton deuxième soucis, je suis pas sur d’avoir compris ce que tu veux faire et sur quoi tu bute, mais je n’ai pas eu mon café du matin encore.

Oui effectivement ça ça devrait fonctionner :slight_smile:
Je ne pensais pas que « ça se faisait » de renvoyer plusieurs types via un converter. Merci !!! Pour le 2è souci je repost ce soir :crying:

Merci encore !

Pour le premier point, ca ne marche pas, car dans ce cas tu ne transformes pas ta coordonnée.
Un moyen simple de faire ce que tu veux, c’est ceci :

<ListBox ItemsSource="{Binding Path=Shapes}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" DataContext={Binding Converter={StaticResource myConverter}}> <TextBlock Text="X : "/> <TextBlock Text="{Binding X}" /> <TextBlock Text=", Y : "/> <TextBlock Text="{Binding Y}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
Ca a aussi l’avantage de n’exécuter ton converter qu’une fois.
Pour le deuxième point, il suffit d’utiliser les propriétés ActualWidth et ActualHeight de ton conteneur.

[quote=« girafologue, post:4, topic: 48995 »]Pour le premier point, ca ne marche pas, car dans ce cas tu ne transformes pas ta coordonnée.
Un moyen simple de faire ce que tu veux, c’est ceci :

<ListBox ItemsSource="{Binding Path=Shapes}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" DataContext={Binding Converter={StaticResource myConverter}}> <TextBlock Text="X : "/> <TextBlock Text="{Binding X}" /> <TextBlock Text=", Y : "/> <TextBlock Text="{Binding Y}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
Ca a aussi l’avantage de n’exécuter ton converter qu’une fois.
Pour le deuxième point, il suffit d’utiliser les propriétés ActualWidth et ActualHeight de ton conteneur.[/quote]

Ah ouai nikel ! Je ne suis vraiment pas à l’aise avec le binding et la redéfinition du DataContext pour tel et tel composant. C’est vraiment puissant !
Concernant le 2è point ActualWidth et ActualHeight du conteneur sont défini à NaN :crying: la seul taille qui est défini c’est la taille de ma Window. Donc il faudrait que je puisse récupérer les « premières valeurs » (ActualHeight et ActualWidth) définis dans mon arbre, et que je me binde dessus. Je pense que ça doit être faisable ça non ? Le tout c’est de savoir comment :slight_smile:

En tout cas je vous remercie pour toutes vos pistes les gars !!!

Attention, ActualWidth et ActualHeight ne sont initialisés qu’après la première passe de layout. Sur l’évènement Load, c’est normal que ce soit à Nan. Si tu te Bind dessus tu verras que la valeur bouge à chaque invalidation de Layout.