Bonjour à vous,
J'ai créé un contrôle utilisateur qui prend pour paramètre un objet d'un type personnalisé.
A regarder les articles sur le sujet, je pense avoir compris les propriétés de dépendances et comment utiliser le contrôle utilisateur. Je n'arrive par contre pas à comprendre comment lui passer en paramètre un objet créé en code behind.
Pour plus de clarté, j'ai reproduit le problème dans un projet simple :
le code XAML du contrôle :
Code xaml : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 <UserControl x:Class="WpfApplication1.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="150" d:DesignWidth="200"> <Grid Height="144" Width="auto"> <ComboBox Height="24" HorizontalAlignment="Stretch" Name="comboBox1" VerticalAlignment="top" Width="auto" SelectionChanged="comboBox1_SelectionChanged" /> <ListBox Height="103" HorizontalAlignment="Stretch" Margin="0,30,0,0" Name="listBox1" VerticalAlignment="Stretch" Width="auto" /> </Grid> </UserControl>
Le code behind du contrôle utilisateur :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public partial class UserControl1 : UserControl { public static DependencyProperty ParcVoituresProperty = DependencyProperty.Register( "ParcVoitures", typeof(string), typeof(Parc)); public Parc ParcVoitures { get { return (Parc)GetValue(ParcVoituresProperty); } set { SetValue(ParcVoituresProperty, value); } } public UserControl1() { InitializeComponent(); if (ParcVoitures != null) { // remplissage de la combobox et de la listbox comboBox1.ItemsSource = ParcVoitures.lsVoitures.Select(x => x.Modele).Distinct(); if (comboBox1.Items.Count > 1) comboBox1.SelectedIndex = 0; LoadVoitures(); } } public void LoadVoitures() { listBox1.ItemsSource = ParcVoitures.lsVoitures.Where(x => x.Marque == comboBox1.SelectedValue.ToString()).Select(x => x.Modele); } private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e) { LoadVoitures(); } }
Le but du contrôle ci-dessus : un visualiseur d'un objet de type "Parc".
Le type "Parc" :
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 public class Parc { public List<Voiture> lsVoitures; public Parc() { lsVoitures = new List<Voiture>(); lsVoitures.Add(new Voiture("Peugeot", "308")); lsVoitures.Add(new Voiture("Renault", "Logan")); lsVoitures.Add(new Voiture("Peugeot", "407")); lsVoitures.Add(new Voiture("Audi", "R8")); lsVoitures.Add(new Voiture("Audi", "A3")); lsVoitures.Add(new Voiture("Renault", "R25")); } } public class Voiture { public string Marque; public string Modele; public Voiture(string pMarque, string pModele) { this.Marque = pMarque; this.Modele = pModele; } } }
L'utilisation dans ma fenêtre principale (c'est là que je bloque) :
Code xaml : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:myCtrl="clr-namespace:WpfApplication1" Title="Window1" Height="300" Width="300"> <Window.Resources> <ObjectDataProvider x:Key="MesVoitures" ObjectType="{x:Type myCtrl:Parc}" ObjectInstance="MonParc" /> <!-- provoque une exception System.InvalidOperationException : "ObjectDataProvider ne peut se voir assigner qu'un ObjectType ou un ObjectInstance, pas les deux." --> </Window.Resources> <Grid> <myCtrl:UserControl1 ParcVoitures="{Binding Source={StaticResource MesVoitures}}" HorizontalAlignment="Left" x:Name="userControl11" VerticalAlignment="Top" Height="195" Width="254" /> </Grid> </Window>
Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 public partial class MainWindow : Window { Parc MonParc = new Parc(); public MainWindow() { InitializeComponent(); } }
Le but est d'utiliser "MonParc" qui va subir des traitements en tâche de fond et de passer son instance au contrôle utilisateur qui permet de visualiser son contenu (ici, dans l'exemple, pas de mécanisme de mise à jour, je veux simplement réussir à lui passer l'instance de l'objet!).
Je comprends dans le message d'exception que je ne fais pas comme il faut.
Cependant, j'ai beau faire des recherches, j'avoue que j'ai du mal avec le binding via XAML.
Comment faire ?
Note sur mes essais :
J'ai essayé en passant par l'attribut "MethodName=GetVoitures" à la place de "ObjectInstance=MonParc" mais lors du passage dans le constructeur du contrôle utilisateur, la propriété "ParcVoitures" est nulle.
En pièce jointe le projet (Visual Studio 2010) décrit ci-dessus.
Partager