30 votes

Lier WPF au membre de classe dans le code derrière

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?

30voto

Robert Rossney Points 43767

Ce que je constate, c'est que la fenêtre de votre nom de classe est - Main, que vous avez ajouté un RecordProp de la propriété, et que vous êtes maintenant en essayant de se lier à l' IsChecked de la propriété de l'élément nommé RecordProp. Je pense que vous êtes un peu confus au sujet de comment travailler les noms.

L'ajout de l' x:Name d'attribut à un élément XAML crée un champ dans la fenêtre de la classe avec ce nom. Cela vous permet de référencer des éléments nommés dans votre code, et il a probablement conduit à penser que la liaison peut faire la même chose.

Mais ce n'est pas contraignant trouve des éléments nommés. L' x:Name attribut aussi prend de l'objet que l'élément exact crée et enregistre sous son nom dans la fenêtre de la portée de nom. (Voir l'article de MSDN sur XAML portées de nom.) C'est ce que la liaison regarde pour résoudre les noms d'éléments. Depuis que vous êtes de ne jamais ajouter l'objet à la portée de nom, réglage de l' ElementName de la propriété sur une liaison de ne pas le trouver.

Il ya un couple de choses que vous pourriez éventuellement faire. Si vous voulez vraiment de se lier à une propriété de la fenêtre, vous pouvez donner un nom à la fenêtre et de se lier à la propriété à l'aide d'un chemin de la propriété:

<Window x:Name="MainWindow" x:Class="Main">
...
   <customcontrol Name="View" IsChecked="
                 {Binding ElementName=MainWindow, 
                  Path=RecordProp.IsViewChecked}" />

Même le plus simple est de définir le contexte de données dans le constructeur:

DataContext = this;

Une fois que vous faites cela, vous pouvez simplement lier à l' RecordProp de la propriété (et de 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 de la fenêtre de contexte de données à autre chose.

Une autre possibilité est de mettre en œuvre la propriété comme ceci:

public Record RecordProp 
{
  get { return (Record)Resources["RecordProp"]; }
  set { Resources["RecordProp"] = value; }
}

Vous pouvez lier à cette utilisation (par exemple) Binding {DynamicResource RecordProp}, Path=IsChecked". Puisque c'est une ressource dynamique, si quelque chose d'extérieur à la fenêtre définit la fenêtre de l' RecordProp de la propriété, les fixations, il mettra à jour - qui est quelque chose qui n'arrivera pas si vous venez de faire RecordProp d'un bien (à moins que vous mettre en œuvre le changement de notification).

27voto

John Bowen Points 14985

Path 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}"
 

7voto

JoeCool Points 1673

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 font tous deux référence au même objet.

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.

3voto

JaredPar Points 333733

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 publiquement la valeur _record et liez-la à la place.

Référence - http://msdn.microsoft.com/en-us/library/ms743643.aspx

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X