2010-03-02 11 views
30

recht einfache Frage, aber kann nicht auf hier scheint eine vollständige Antwort zu finden ...WPF Binden an Klasse Mitglied in Code hinter

Ich brauche in XAML auf eine Eigenschaft einer Klasse Mitglied in Code-Behind Databind.

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

Wo der Code hinter wie folgt aussieht:

class Main 
{  
    ... 
    private Record _record; 
    public Record RecordProp 
    { 
     get { return _record; } 
    } 
    ... 
} 


class Record 
{ 
    public bool IsViewChecked 
    { 
    get; set; 
    } 
} 

Was ich habe jetzt nicht funktioniert, was mache ich falsch?

Antwort

26

Pfad braucht eine Quelle zu gehen gegen (Quelle, Datacontext, Relative, Elementname). ElementName kann nur verwendet werden, um auf Elemente zu verweisen, die in XAML mit ihrem x: Name deklariert sind. Versuchen Sie stattdessen zu Ihrem Fenster als Quelle zu verweisen:

IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}" 
3

Datenbindung funktioniert nicht gegen private Felder. Es ist stattdessen für öffentliche Objekte gedacht. Versuchen Sie, den Wert _record öffentlich verfügbar zu machen und stattdessen an diesen Wert zu binden.

Referenz - http://msdn.microsoft.com/en-us/library/ms743643.aspx

+0

Das öffentliche Eigentum hatte keine Auswirkungen. – jaws

+0

@ user258651 Ich denke, dass Sie den Bindungskontext auch für das Hauptfenster aktualisieren müssen, damit es standardmäßig in die Hauptklasse zurückkehrt. Eine Weile her, seit ich das gesehen habe. – JaredPar

29

Was ich hier zu sehen ist, dass Ihre Fenster-Klassennamen Main ist, dass Sie eine RecordProp Eigenschaft hinzugefügt haben, und dass Sie versucht nun, an die IsChecked-Eigenschaft des Elements RecordProp zu binden. Ich denke du bist etwas verwirrt darüber, wie Namen funktionieren.

Das Hinzufügen des x:Name-Attributs zu einem XAML-Element erstellt ein Feld in der Fensterklasse mit diesem Namen. Auf diese Weise können Sie auf benannte Elemente in Ihrem Code verweisen, und Sie haben wahrscheinlich zu der Annahme geführt, dass die Bindung dasselbe bewirken kann.

Aber das ist nicht wie bindende benannte Elemente findet. Das x:Name Attribut auch nimmt das Objekt, das das XAML-Element erstellt und registriert es unter diesem Namen im Namescope des Fensters. (Siehe MSDN's article on XAML namescopes.) Das ist, was Bindung betrifft, um Elementnamen aufzulösen. Da Sie das Objekt nie dem Namescope hinzufügen, wird die Eigenschaft ElementName für eine Bindung nicht gefunden.

Es gibt ein paar Dinge, die Sie möglicherweise tun könnten. Wenn Sie wirklich auf eine Eigenschaft des Fensters binden möchten, können Sie das Fenster einen Namen geben und auf die Eigenschaft binden, um eine Eigenschaft Pfad:

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

Noch einfacher ist es, nur den Datenkontext im Konstruktor festgelegt:

DataContext = this; 

Sobald Sie das tun, können Sie einfach binden an die RecordProp Eigenschaft (und jede andere Eigenschaft des Fensters) wie folgt aus:

<customControl Name="View" IsChecked={Binding RecordProp.IsChecked}/> 

natürlich, dass nicht, wenn yo arbeiten Sie müssen den Datenkontext des Fensters auf etwas anderes setzen.

Eine andere Möglichkeit ist es, die Eigenschaft wie folgt umzusetzen:

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

Sie binden sich an diese mit (zum Beispiel) Binding {DynamicResource RecordProp}, Path=IsChecked" können.Da es sich um eine dynamische Ressource handelt, wird, wenn etwas außerhalb des Fensters die RecordProp -Eigenschaft des Fensters einstellt, die Bindungen zu diesem Fenster aktualisiert - was nicht der Fall ist, wenn Sie nur RecordProp als Eigenschaft festlegen (sofern Sie keine Änderungsbenachrichtigung implementieren).

+0

Eine Anmerkung, DataContext sollte nicht im Window-Konstruktor, sondern im Loaded-Event-Handler gesetzt werden. Das Festlegen in einem Konstruktor funktionierte für ObservableCollection nicht, wenn ich es innerhalb des Loaded-Ereignisses füllte. –

+2

Anstatt den "DataContext" von 'Windows' aus dem Code zu setzen, können Sie dies einfach dem XAML von' Windows' hinzufügen: 'DataContext =" {Binding RelativeSource = {RelativeSource Self}} ' –

6

Ich glaube, ich habe eine einfachere Antwort als die bisher genannten. fügen Sie diese einfach an die Fenster-Deklaration (der erste Tag) in XAML:

x:Name="this" 

Dann können Sie wie folgt Databind:

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

ich, wenn C# beschwert sich daraufhin überprüft, dass es bereits eine " dies, "und es nicht, denke ich, weil sie sich beide auf das exakt gleiche Objekt beziehen.

Dies ist die Lösung, die ich verwendet habe, als ich auf das gleiche Problem stieß, und ich fand es sehr intuitiv zu bedienen.

+0

Gibt es dafür einen Grund? Um es auf diese Weise zu machen? Ich habe die anderen Lösungen ohne Erfolg ausprobiert. Dies ist der einzige Weg, wie ich es mit meinen noob C# Fähigkeiten arbeiten konnte. –

+1

Wenn Sie downvote, kommentieren Sie bitte, warum Sie denken, dies ist ein schlechte Lösung. – JoeCool

Verwandte Themen