2010-03-02 10 views
30

Całkiem proste pytanie, ale nie wydaje się znaleźć pełną odpowiedź tutaj ...WPF Bind do członka klasy w kodzie za

Ptrzebuję databind w XAML do właściwości danego członka klasy w kodzie.

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

Gdzie związany kod wygląda następująco:

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


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

Co mam teraz nie działa, co robię źle?

Odpowiedz

26

Ścieżka potrzebuje Źródło iść przeciw (Source, DataContext, RelativeSource, ElementName). ElementName może być użyty tylko w odniesieniu do elementów zadeklarowanych w XAML przez ich x: Name. Spróbuj zamiast tego zwrócić do okna jako źródła:

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

Powiązanie danych nie działa z prywatnymi polami. Jest przeznaczony dla nieruchomości publicznych. Spróbuj publicznie wyświetlić wartość _record i zamiast tego ustaw ją.

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

+0

Właściwość publiczna nie miała żadnego wpływu. – jaws

+0

@ user258651 Wydaje mi się, że musisz zaktualizować kontekst bindowania, aby okno główne domyślnie powróciło do klasy głównej. Minęło trochę czasu, odkąd na to patrzyłem. – JaredPar

29

Co widzę tutaj jest to, że nazwa klasy okna jest Main, że dodasz właściwość RecordProp do niego i że jesteś teraz próbuje połączyć się z właściwością o nazwie RecordProp. Myślę, że jesteś trochę zdezorientowany, jak działają nazwy.

Dodanie atrybutu x:Name do elementu XAML tworzy pole w klasie okna o tej nazwie. To pozwala ci odwoływać się do nazwanych elementów w twoim kodzie i prawdopodobnie doprowadziło cię do przekonania, że ​​wiązanie może zrobić to samo.

Ale to nie jest sposób wiązania znalezionych nazwanych elementów. Atrybut x:Nametakże przenosi obiekt, który element XAML tworzy i rejestruje pod tą nazwą w oknie imiennym okna. (Zobacz MSDN's article on XAML namescopes.) To właśnie wygląda na powiązanie, aby rozwiązać nazwy elementów. Ponieważ nigdy nie dodajesz obiektu do namescope, ustawienie właściwości ElementName na powiązaniu nie spowoduje jej znalezienia.

Jest kilka rzeczy, które można zrobić. Jeśli naprawdę chcą wiązać się z majątku oknie można nadać oknu nazwę i wiążą się z posesji przy użyciu ścieżki właściwość:

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

Jeszcze prostsze jest po prostu ustawić kontekstu danych w konstruktorze:

DataContext = this; 

Gdy to zrobisz, możesz po prostu powiązać z właściwością RecordProp (i innej własności okna) jak poniżej:

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

oczywiście, że nie będzie działać, jeśli yo Potrzebujesz kontekst danych okna, aby ustawić coś innego.

Inną możliwością jest wprowadzenie własności takiego:

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

można powiązać to z użyciem (na przykład) Binding {DynamicResource RecordProp}, Path=IsChecked".Ponieważ jest to zasób dynamiczny, jeśli coś poza oknem ustawia jego właściwość, odradzą się wiązania - co nie będzie miało miejsca, jeśli po prostu ustawisz właściwość jako własność (chyba że zaimplementujesz powiadomienie o zmianie).

+0

Jedna nuta, DataContext nie powinna być ustawiona w konstruktorze Window, ale w Loaded event handler. Ustawienie tego w konstruktorze nie działa dla mnie dla ObservableCollection, gdy wypełniłem go wewnątrz zdarzenia Loaded. –

+2

Zamiast ustawiać 'DataContext'' Windows 'z kodu, możesz po prostu dodać to do XAML' Windowsa: 'DataContext =" {Binding RelativeSource = {RelativeSource Self}} ' –

6

Uważam, że mam prostszą odpowiedź niż te, które do tej pory podano. Wystarczy dodać to do deklaracji okna (to pierwszy tag) w XAML:

x:Name="this" 

Następnie można databind tak:

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

sprawdziłem aby zobaczyć czy C# skarży się, że tam już jest " to, "i tak nie było, chyba dlatego, że obaj odnoszą się do dokładnie tego samego obiektu.

To jest rozwiązanie, którego użyłem, gdy wpadłem na ten sam problem i stwierdziłem, że jest on bardzo intuicyjny w użyciu.

+0

Czy istnieje powód nie zrobić to w ten sposób? Próbowałem innych rozwiązań bez powodzenia.Jest to jedyny sposób, w jaki udało mi się uzyskać to działając z moimi umiejętnościami noob C# –

+1

Jeśli zarzuciłeś, proszę skomentuj, dlaczego uważasz, że jest to złe rozwiązanie. – JoeCool

Powiązane problemy