Question assez simple, mais ne semble pas trouver une réponse complète ici ...
J'ai besoin de lier des données dans xaml à une propriété d'un membre de classe dans codebehind.
<Window x:Class="Main">
<customcontrol Name="View" IsChecked="{Binding ElementName=RecordProp, Path=IsViewChecked}" />
...
À quoi ressemble le code derrière:
class Main
{
...
private Record _record;
public Record RecordProp
{
get { return _record; }
}
...
}
class Record
{
public bool IsViewChecked
{
get; set;
}
}
Ce que j'ai maintenant ne fonctionne pas, qu'est-ce que je fais mal?
Le chemin a besoin d'une source pour aller contre (Source, DataContext, RelativeSource, ElementName). ElementName ne peut être utilisé que pour faire référence aux éléments déclarés en XAML par leur x: Name. Essayez plutôt de pointer vers votre fenêtre comme source:
IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
Ce que je vois ici, c'est que le nom de classe de votre fenêtre est Main
, que vous y avez ajouté une propriété RecordProp
et que vous essayez maintenant de vous lier à IsChecked
propriété de l'élément nommé RecordProp
. Je pense que vous êtes un peu confus sur la façon dont les noms fonctionnent.
Ajout du x:Name
l'attribut à un élément XAML crée un champ dans la classe window avec ce nom. Cela vous permet de référencer des éléments nommés dans votre code, et cela vous a probablement amené à penser que la liaison peut faire la même chose.
Mais ce n'est pas ainsi que la liaison trouve des éléments nommés. Le x:Name
attribute prend également l'objet créé par l'élément XAML et l'enregistre sous ce nom dans la portée de la fenêtre. (Voir article de MSDN sur les étendues de noms XAML. ) C'est ce que la liaison examine pour résoudre les noms d'élément. Étant donné que vous n'ajoutez jamais l'objet à l'étendue de noms, la définition de la propriété ElementName
sur une liaison ne le trouvera pas.
Il y a deux ou trois choses que vous pourriez imaginer faire. Si vous voulez vraiment vous lier à une propriété de la fenêtre, vous pouvez donner un nom à la fenêtre et la lier à la propriété en utilisant un chemin de propriété:
<Window x:Name="MainWindow" x:Class="Main">
...
<customcontrol Name="View" IsChecked="
{Binding ElementName=MainWindow,
Path=RecordProp.IsViewChecked}" />
Encore plus simple est de simplement définir le contexte de données dans le constructeur:
DataContext = this;
Une fois que vous faites cela, vous pouvez simplement vous lier à la propriété RecordProp
(et à toute autre propriété de la fenêtre) comme ceci:
<customControl Name="View" IsChecked={Binding RecordProp.IsChecked}/>
Bien sûr, cela ne fonctionnera pas si vous avez besoin que le contexte de données de la fenêtre soit défini sur autre chose.
Une autre possibilité consiste à implémenter la propriété comme ceci:
public Record RecordProp
{
get { return (Record)Resources["RecordProp"]; }
set { Resources["RecordProp"] = value; }
}
Vous pouvez vous y lier en utilisant (par exemple) Binding {DynamicResource RecordProp}, Path=IsChecked"
. Puisqu'il s'agit d'une ressource dynamique, si quelque chose d'extérieur à la fenêtre définit la propriété RecordProp
de la fenêtre, les liaisons vers celle-ci seront actualisées - ce qui ne se produira pas si vous faites simplement de RecordProp
une propriété (sauf si vous implémentez une notification de modification).
Je pense avoir une réponse plus simple que celles qui ont été données jusqu'à présent. Ajoutez simplement ceci à la déclaration de fenêtre (la toute première balise) en XAML:
x:Name="this"
Ensuite, vous pouvez lier des données comme ceci:
<customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" />
J'ai vérifié si C # se plaignait qu'il existe déjà un "ceci", et il ne l'a pas fait, je suppose parce qu'ils se réfèrent tous deux au même objet exact.
C'est la solution que j'ai utilisée lorsque j'ai rencontré le même problème et je l'ai trouvée très intuitive à utiliser.
La liaison de données ne fonctionnera pas contre les champs privés. Il est plutôt destiné aux propriétés publiques. Essayez d'exposer la valeur _record
publiquement et y lier à la place.
Référence - http://msdn.Microsoft.com/en-us/library/ms743643.aspx