none
UserControl und DataBinding RRS feed

  • Frage

  • Hallo an die Experten,

    ich habe ein XAML-Formular welches Daten aus einer List<> anzeigen soll. Das funktioniert soweit mit einem ItemTemplate. Dabei ist die Anzeige recht statisch.

    Nun wollte ich das ItemTemplate durch ein UserControl ersetzen. Dieses hat momentan nur eine TextBox.

    class MyUserControl

    {

      public MyUserControl()

      {

          InitialComponents();

       }

        public string txtDevice

        {

           get { return txtDevice.Text }

           set { txtDevice.Text = value}

        }

    }

    Das ist der Code. Wenn ich nun im XAML angebe:

    <local:MyUserControl txtDevice="{Binding=Title}">

    </local:MyUserControl>

    Hier wird aber ein Fehler erzeugt, dessen Fehlertext unbekannt ist. Wenn ich txtDevice="{Binding=Title}" weglasse, so erscheint das UserControl mit den Standardwerten...

    Wo liegt mein Fehler?

    Mfg

    Micha

    Mittwoch, 10. September 2014 19:17

Antworten

  • Hallo,
    ich gehe mal davon aus, das du an einer App programmierst.

    Ich kann zwar mit deinem Code keine Exception oder einen Kompilierfehler erzeugen, habe aber eine Idee was der Fehler sein könnte.
    Wie verarbeitest du denn den Wert der DeviceName-Eigenschaft im UserControl (UC)?

    Wenn du einfach nur den DataContext des UC auf das UC selbst legst, könntest du im XAML des UC einfach an die DeviceName-Eigenschaft binden. Dadurch würde jedoch im XAML des GridViews die Title-Eigenschaft ebenfalls im UC gesucht werden.
    Das Einfachste dürfte sein, im XAML des UC einfach die Title-Eigenschaft zu binden:

    <TextBlock Foreground="Yellow" Text="{Binding Title}"/>

    Da der DataContext eines jeden DataTemplates auf das jeweilige Item gelegt wird, wird so auch die Title-Eigenschaft innerhalb des Controls problemlos gefunden. Der "Umweg" über eine weitere Eigenschaft wird somit unnötig.

    Eine andere Möglichkeit besteht darin im DataTemplate ein Hilfselement einzusetzen:

    <DataTemplate>
        <StackPanel>
            <TextBlock Text="{Binding Title}" x:Name="helper" Visibility="Collapsed"/>
            <local:DeviceView DeviceName="{Binding Text, ElementName=helper}"/>
        </StackPanel>
    </DataTemplate>
    Dadurch kann der TextBlock den Text mit Hilfe des DataContext abfragen und das UC über den TextBlock an die Title-Eigenschaft heran kommen.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Freitag, 12. September 2014 15:47

Alle Antworten

  • Hallo,
    vorrausgesetzt du hast dein UserControl richtig in das Template eingebaut, liegt der Fehler am Bindungsausdruck. Das = muss weg:
    {Binding Title}
    Das ist die Kurzform von
    {Binding Path=Title}
    Gibt also an, wie die zu bindende Eigenschaft heißt.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Mittwoch, 10. September 2014 19:46
  • Hallo Tom,

    sorry, ich hatte den Code aus dem Gedächtnis geschrieben. Bei mir steht {Binding Title}.

    Das ganze Grid sieht folgendermaßen aus:

    <GridView

      ItemsSource="{Binding Source={StaticResource itemsViewSource}}"

      <GridView.ItemTemplate>

         <DataTemplate>

            <local:DeviceView DeviceName="{Binding Title}">

            </local:DeviceView>

          </DataTemplate>

        </GridView.ItemTemplate>

    </GridView>

    Dabei ist DeviceView mein UserControl welches (momentan nur) ein öffentliches Member DeviceName hat.

    Irgendwo klemmts, aber ich sehe nicht wo.

    Freitag, 12. September 2014 14:49
  • Hallo,
    ich gehe mal davon aus, das du an einer App programmierst.

    Ich kann zwar mit deinem Code keine Exception oder einen Kompilierfehler erzeugen, habe aber eine Idee was der Fehler sein könnte.
    Wie verarbeitest du denn den Wert der DeviceName-Eigenschaft im UserControl (UC)?

    Wenn du einfach nur den DataContext des UC auf das UC selbst legst, könntest du im XAML des UC einfach an die DeviceName-Eigenschaft binden. Dadurch würde jedoch im XAML des GridViews die Title-Eigenschaft ebenfalls im UC gesucht werden.
    Das Einfachste dürfte sein, im XAML des UC einfach die Title-Eigenschaft zu binden:

    <TextBlock Foreground="Yellow" Text="{Binding Title}"/>

    Da der DataContext eines jeden DataTemplates auf das jeweilige Item gelegt wird, wird so auch die Title-Eigenschaft innerhalb des Controls problemlos gefunden. Der "Umweg" über eine weitere Eigenschaft wird somit unnötig.

    Eine andere Möglichkeit besteht darin im DataTemplate ein Hilfselement einzusetzen:

    <DataTemplate>
        <StackPanel>
            <TextBlock Text="{Binding Title}" x:Name="helper" Visibility="Collapsed"/>
            <local:DeviceView DeviceName="{Binding Text, ElementName=helper}"/>
        </StackPanel>
    </DataTemplate>
    Dadurch kann der TextBlock den Text mit Hilfe des DataContext abfragen und das UC über den TextBlock an die Title-Eigenschaft heran kommen.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Freitag, 12. September 2014 15:47
  • Hallo zusammen,

    bin jetzt einen Schritt weiter. Das Problem war, dass im UserControl noch die entsprechenden Dependency-Properties registriert werden mussten.

    Das habe ich jetzt nachgeholt und nun kompiliert und läuft die Sache erstmal.

    Aber: Die entsprechenden Daten werden nicht angezeigt. Hier lauert wohl mein nächstes Problem.

    In der Code-Behind-Datei habe ich die Zeile:

    this.DefaultViewModel["Items"] = MeineDaten.

    Im Beispiel besteht MeineDaten aus einer List<> mit 3 Einträgen. Jedes Element der Liste hat eine öffentliche Eigenschaft "Title" für das Binding. Ich sehe nun, dass mein UserControl tatsächlich 3 Mal erzeugt wird, jedoch wird der Wert für Title nicht übernommen.

    Darf ich hier nicht mit einer List<> arbeiten?

    Gruß

    Micha

    Samstag, 13. September 2014 13:40
  • Hallo,

    bin jetzt einen Schritt weiter. Das Problem war, dass im UserControl noch die entsprechenden Dependency-Properties registriert werden mussten.

    Zeige die DP bitt mal - vielleicht hast du noch etwas vergessen.

    Aber: Die entsprechenden Daten werden nicht angezeigt. Hier lauert wohl mein nächstes Problem.

    Was zeigt denn das Ausgabe-Fenster beim Debuggen an? Wenn eine Datenbindung nicht funktioniert, wird dort eine Fehlermeldung erscheinen.

    Darf ich hier nicht mit einer List<> arbeiten?

    Doch, darfst du. Solange sich die Daten nicht ändern, ist das auch kein Problem - sonst wäre eine ObservableCollection besser geeignet.

    Wenn du der DP eine CallBack-Methode hinzufügst, wird diese denn aufgerufen (BreakPoint setzen)? Was steht in den EventArgs, speziell die NewValue-Eigenschaft?

    IOch vermute nach wie vor ein Problem mit dem DataContext - hast du meine 2 Lösungen getestet?


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Samstag, 13. September 2014 13:55
  • Hallo Tom,

    ich gebe an der Stelle erstmal auf und fülle die UserControl zu Fuss in das GridView ein. Das funktioniert soweit. Sind zwar ein paar Codezeilen mehr, aber am Ende sieht es genauso aus.

    Ich denke, mir fehlt hier zu viel Hintergrundwissen. Ich habe im Prinzip das Hub-Beispiel genutzt, welches mit VS2013 Express installiert wird und dieses wollte ich entsprechend modifizieren...

    Was mir noch aufgefallen ist: Wenn ich im XAML die folgenden Zeile nutze:

    <TextBlock Text="{Binding Title}"></TextBlock>

    <local:DeviceView DeviceName="{Binding Title}"></local:DeviceView>

    So wird mir im TextBlock der richtige Wert angezeigt. Im UserControl (DeviceView) leider nicht. Fehlermeldungen beim Debuggen bezüglich des Bindings erscheinen keine.

    Gruß

    Micha

    Samstag, 13. September 2014 16:16