Zugriff auf UserControl->Controls mittels XAML

  • WPF

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    Zugriff auf UserControl->Controls mittels XAML

    Hallo Leute,

    ich stehe mal wieder auf dem Schlauch.
    Ich nutze eine Liste, die durch ein StackPanel gestackt wird. Nun sollen in diesem StackPanel aber mehrere Elemente pro Stack eingetragen werden. Aus diesem Grund habe ich mir ein UserControl erstellt, welches selbst von StackPanel erbt. Diesem habe ich dann ein Image (x:Name="StackImg"), ein TextBlock (x:Name="StackTB") sowie einen Button und eine CheckBox (x:Name="StackBtn" sowie StackCheck") zugewiesen. (Stack.Orientation = Orientation.Left)
    Das Bild im Designer sieht auch genau so aus, wie ich es brauche. Soweit so gut.
    Da ich die Liste anhand von Datenquellen lade, initialisiere ich sie mittels Code-Behind. Das ist auch recht einfach, da ich mittels foreach-Schleife alle Elemente befüllen kann

    Die Image-Source des Bildes rufe ich in der foreach Schleife durch StackImg.Source = XXX ab.
    Ich nehme also den Namen des UserControls, dann seine Eigenschaft für den Namen des Bildes und dann den Namen der Eigenschaft des Bildes selbst.

    Wie aber kann ich über XAML darauf zugreifen? Meine erste Überlegung war, dass ich dem UC Properties geben muss und die StackImg.Source an die Property binden muss und dann in XAML die Property befüllen. Aber gibt es dafür noch einen anderen Weg? Wenn nicht, muss ich also für jedes UnterControl (für deren Eigenschaften) jeweils eigene Properties einbinden?

    Zu meiner Schande muss ich aber gestehen, dass ich von VB.NET mittlerweile auf C# gewechselt bin... aber vielleicht hilft man dem frevelhaften Schelm ja dennoch weiter :P :whistling:
    Hallo @PadreSperanza

    PadreSperanza schrieb:

    Aus diesem Grund habe ich mir ein UserControl erstellt, welches selbst von StackPanel erbt.

    Das ist garnicht notwendig. Es reicht ein ganz normales UserControl.

    PadreSperanza schrieb:

    Wie aber kann ich über XAML darauf zugreifen?

    Da liegt der Hase im Pfeffer. Über CodeBehind ist sowas in der WPF nur sehr mühsahm zu bewerkstelligen. In der WPF Arbeitet man mit Binding. Du wirst sehen das ist total easy.

    Du hast in deinem HauptControl (Window) deinen CodeBehind wo die Daten geladen werden. Hier befindet sich auch deine Liste. Die Liste wird mittels BindingSource auf die Daten gebunden.
    In der Liste befindet sich ein DataTemplate welches dein UserControl befindet. Dieses erbt den DatenContext wodurch du nur noch die Eigenschaften angeben musst und fertig.

    Ist jetzt per Text recht schwer zu erklären. Du kannst aber gerne etwas Code zeigen. (Den XAML des UserControl, den Code mit den Daten und den XAML des Window) dann kann ich dir gerne ein kleines Beispiel zusammenstellen.

    Ansonsten schau dir mal folgende Kapitel meiner Tutorialreihe an wo genau dies durchgenommen wird:

    2.1.4.1 Was ist DataBinding? Das Konzept dahinter

    2.1.4.2 Binding anhand einfacher Beispiele und Klassen
    2.1.4.5 Binding über DataTemplates

    Grüße
    Sascha

    PS: Das Beispiel kann ich frühesten heute Abend machen da ich den ganzen Tag unterwegs bin.
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ja, okay... da hab ich mich etwas doof ausgedrückt.

    Das UserControl erbt nicht von StackPanel, sondern hat ein StackPanel als obersten Container. Der XAML Code sieht wie folgt aus:

    Quellcode

    1. <UserControl x:Class="AppHolder"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    5. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6. xmlns:local="clr-namespace:NTSR"
    7. mc:Ignorable="d"
    8. d:DesignHeight="100" d:DesignWidth="100">
    9. <StackPanel>
    10. <TextBlock Height="20" x:Name="StackTB"/>
    11. <Image x:Name="StackIMG" Height="60"/>
    12. <Button x:Name="StackBtn" Height="20"/>
    13. </StackPanel>
    14. </UserControl>


    und das erzeugt auch das entsprechende UserControl.

    Wenn ich das nun im MainWindow einfüge, schreibe ich einfach:

    Quellcode

    1. <local:AppHolder />


    Aber ich kann im MainWindow nicht direkt auf "StackIMG" z.B. zugreifen? Oder gibt es dafür doch eine andere Möglichkeit als das per Binding auf eine Property?

    Also ich möchte zB. die Image.Source über das MainWindow setzen und zwar ähnlich wie wenn ich bei einem einfachen Image

    Quellcode

    1. ​<Image Source="..\test.png"/>
    schreiben würde.

    Ich dachte erst, das ginge vielleicht über den Namen des Controls im UC:

    Quellcode

    1. ​<local:AppHolder StackIMG.Source="..\test.png"/>


    Aber so scheint es nicht zu funktionieren. :)
    Du kannst auch im CodeBehind darauf zugreifen.
    So im XAML kannst du das Image Objekt ja nicht dynamisch füllen.

    Aber nur so am Rande. Glaub mir. Du tust dir keinen gefallen wenn du mit der WPF so arbeitest wie mit WinForms.
    Binding ist fest in der WPF verankert - die WPF baut komplett auf Binding auf. Je früher du dich diesbezüglich umstellst desto besser für dich. Ich kann dir nur den Rat geben da ich es selbst auf die harte Tour erfahren musste.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ja, ich arbeite mich da gerade auch Schritt für Schritte ran. Und deine Tutorials helfen auch, aber im Augenblick bin ich noch nicht soweit, alles zu durchschauen. Deshalb ist ja hier die Frage, wie ich die Image.Source des UserControls im MainWindow binden kann?

    Ich hab mich in Dependency Properties eingelesen, aber irgendwie springt der Funke da leider noch immer nicht ganz rüber.
    Hallo

    PadreSperanza schrieb:

    Deshalb ist ja hier die Frage, wie ich die Image.Source des UserControls im MainWindow binden kann?

    Ah, ok., Der Satz hat mich etwas verwirrt.

    PadreSperanza schrieb:

    Oder gibt es dafür doch eine andere Möglichkeit als das per Binding auf eine Property?


    Nur kurz, wie liest du denn die Daten ein. Also im "außersten" Control wie z.b. dem MainWindow. Nur damit ich für dich ein nachvollziehbares Beispiel erstellen kann.

    Grüße
    Sascha

    EDIT: Jetzt wo ich mir das ganze nochmals durchlese muss ich nochmal nachfragen. Willst du von "außen" wirklich manuell das Bild in XAML setzen oder ist der Pfad des Bildes im code den du einliest und du willst "nur" binden?
    Wenn du ihn außen setzen willst benötigst du unbedingt ein DependencyProperty. Ist aber Easy mit dem Assistenten in VS.

    Gruck mal hier: 2.1.5.3 Eigene DependencyProperties in einem UserControl implementieren
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ ()

    Ich lasse eine Datei einlesen, die auf andere existierende Dateien verweist und deren ICO-File einliest und diese File möchte ich dann mittels Konverter an die Source weiterreichen.

    Das funktioniert komplett im Code-Behind auch ohne Probleme. Nur komme ich nicht darauf, wie ich das erstellen muss, damit ich das über XAML binden kann, damit ich danach nur noch die Property im Codebehind ändern muss und alles andere sich selbst aktualisiert.

    Vielen Dank für den Link zum nächsten Tutorial, das ziehe ich mir direkt rein :)


    Edit: Jetzt habe ich mich soweit rein gelesen und das verstehe ich auch als solches... aber:
    Warum brauche ich manchmal die Methode DependencyProperty.Register(...) und bei anderen DependencyProperties dann zum Beispiel nicht? Ich habe eine Klasse MetaData, in der habe ich die Properties erstellt und dort funktionieren die ohne MetaData, während ich aber im UserControl ohne das Register die Properties nicht als Kontext auswählen kann, auch nicht als DataContext.

    Und brauche ich bei der Variante mit Register-Methode dennoch ein NotifyChanged() im Set-Zweig?
    Viele Grüße
    Padre

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „PadreSperanza“ ()

    PadreSperanza schrieb:

    damit ich danach nur noch die Property im Codebehind ändern muss und alles andere sich selbst aktualisiert.

    Ja, und genau das geht NUR mittels Binding. Über Binding wir quasi die Source Eigenschaft des ImageObjekts auf die Porperty deines Codes gebunden. Änderst du den Wert des Backingfields des Properties wird automatisch das Bild aktualisiert.

    Gerne mach ich dir am Abend ein rudimentäres Beispiel.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo

    Ich hatte heute irgendwie echt Lust war zu basteln.

    Also habe ich schnell ein kleines Beispiel gebastelt welches Bilder auf einem Ordner inkl. Unterordnern sucht. Auf die performance oder sowas hab ich jetzt nicht geachtet.

    Mir war wichtig das alles für dich dabei ist. Binding auf andere Controls, Binding an die Klasse. Binding der Liste (ItemsControl), Binding von Button auf einen Command, Converter, DataTrigger usw.

    In dem ItemsControl ist ein DataTemplate. Das ImageUserControl. In diesem UserControl befindet sich wie du es willst ein Image und ein Button. Das Image ist per Binding an ein Property der KLasse ImageObject gebunden. Der Button an ein Command in dieser Klasse. Mit klickt auf den Button öffnet sich dann das Bild im Standardprogramm.

    Wenn du Fragen hast kannst du gerne Fragen.

    Grüße
    Sascha
    Bilder
    • 11.png

      12,12 kB, 782×439, 120 mal angesehen
    • 12.png

      426,14 kB, 781×440, 102 mal angesehen
    • 13.png

      545,21 kB, 780×440, 116 mal angesehen
    Dateien
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Wow, super danke!

    Ich schaue mir das nach dem Wochenende an, dann habe ich vielleicht etwas Zeit dafür.

    Aber kannst du mir noch den Unterschied erklären, warum man manchmal über die Register Methode geht und manchmal die Propertys mit Einbindung von NotifyChanged implementiert?
    So, nun melde ich mich mal wieder zu Wort:

    Vielen Dank für das ausführliche Beispiel, das in der Tat einige Bindings enthält, die ich so noch nicht kannte. Das hat mir in der Tat ein großes Stück weitergeholfen. Ein Großteil meines Projektes konnte ich so auf Bindings erweitern. Leider bin ich noch nicht so ganz mit dem MVVM vertraut, weshalb ich mich da weiter rein lesen muss. Aber du hast mir damit bei mehreren Dingen geholfen :)

    PadreSperanza schrieb:

    Aber kannst du mir noch den Unterschied erklären, warum man manchmal über die Register Methode geht und manchmal die Propertys mit Einbindung von NotifyChanged implementiert?

    Die Frage verstehe ich leider nicht ganz. Welche Register-Methode?

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##