2010-03-02 10 views
30

question assez simple, mais ne peut pas sembler trouver une réponse complète ici ...WPF Bind à un membre de la classe dans le code derrière

Je dois DataBind en XAML à une propriété d'un membre de la classe dans behind.

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

Lorsque le code ressemble derrière comme:

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, ce que je fais mal?

Répondre

26

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 nom 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}" 
3

La liaison de données ne fonctionnera pas avec les champs privés. C'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

+0

La propriété publique n'a eu aucun effet. – jaws

+0

@ user258651 Je pense que vous devez également mettre à jour le contexte de liaison pour que la fenêtre principale retourne par défaut à la classe Main. Été un certain temps depuis que j'ai regardé cela cependant. – JaredPar

29

Ce que je vois ici est qui est Main, que vous avez ajouté une propriété RecordProp au nom de la classe de la fenêtre, et que vous êtes essaie maintenant de lier à la propriété IsChecked de l'élément nommé RecordProp. Je pense que vous êtes un peu confus sur la façon dont les noms fonctionnent. L'ajout de l'attribut x:Name à un élément XAML crée un champ dans la classe de fenêtre portant 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. L'attribut x:Nameégalement prend l'objet que l'élément XAML crée et enregistre sous ce nom dans la portée de la fenêtre. (Voir MSDN's article on XAML namescopes.) C'est ce que la liaison regarde pour résoudre les noms d'éléments. Étant donné que vous n'ajoutez jamais l'objet à l'objet Namescope, la propriété ElementName sur une liaison ne le trouvera pas.

Il y a plusieurs choses que vous pourriez faire. Si vous voulez vraiment lier à une propriété de la fenêtre, vous pouvez donner à la fenêtre un nom et se lier à la propriété à l'aide d'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 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 yo Vous avez besoin que le contexte de données de la fenêtre soit défini sur 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 à cela en utilisant (par exemple) Binding {DynamicResource RecordProp}, Path=IsChecked".Comme c'est une ressource dynamique, si quelque chose d'extérieur à la fenêtre définit la propriété RecordProp de la fenêtre, ses liaisons seront rafraîchies - ce qui ne se produira pas si vous ne faites que RecordProp une propriété (sauf si vous implémentez une notification de modification).

+0

Une note, DataContext doit être définie non dans le constructeur de fenêtre, mais dans le gestionnaire d'événements Loaded. Définir cela dans un constructeur n'a pas fonctionné pour moi pour ObservableCollection quand je l'ai rempli dans l'événement Loaded. –

+2

Au lieu de définir le 'DataContext'' Windows' du code, vous pouvez simplement l'ajouter au XAML 'Windows':' DataContext = "{Relational RelativeSource = {RelativeSource Self}}' –

6

Je crois que j'ai une réponse plus simple que celles énoncées jusqu'ici. Il suffit d'ajouter cela à la déclaration de la fenêtre (la première tag) en XAML:

x:Name="this" 

Ensuite, vous pouvez DataBind comme ceci:

<customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" /> 

J'ai vérifié pour voir si C# se plaint qu'il ya déjà un " ceci, "et ce n'est pas le cas, je suppose, car ils se réfèrent tous les deux 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é très intuitif à utiliser.

+0

Y at-il une raison non J'ai essayé les autres solutions sans succès.C'est la seule façon que j'ai pu utiliser avec mes compétences noob C# –

+1

Si vous downvote, s'il vous plaît commenter pourquoi vous pensez que c'est un mauvaise solution. – JoeCool