WPF Datagrid Binding an ein Custom Usercontrol

  • WPF

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Hotdogxxxx.

    WPF Datagrid Binding an ein Custom Usercontrol

    Hallo Ihr WIssenden,

    ich habe mir ein eigenes Textbox Usercontol erstellt und möchte dieses in ein DataGrid einfügen. Hierzu habe ich eine Klasse erstellt, welches mein UserControl beinhaltet. Diese Klasse habe ich mit dem DataGrid verbunden. Wenn ich die Spalten des DataGrids automatisch anlege, wird die Spalte mit dem UserControl nur mit dem Projektnamen und dem Namen des Usercontrols befüllt während die Spalte mit dem Vornamen ordnungsgemäß befüllt wird. Ich dachte, dies liegt daran, dass die Spalten im Default als Textspalten angelegt werden. Aus diesem Grund habe ich nochmal versucht die Spalten manuell im Xaml anzulegen. Aber hier schaffe ich es nicht die Text Eigenschaft meiner eigenen Textbox mit dem Inhalt der Spalte Vorname zu verbinden. Wenn ich den Text Inhalt manuell im Code befülle funktioniert es wie gewollt. Wenn ich den Textinhalt aber versuche mit der Spalte zu binden wird mir ein Fehler ausgeworfen.


    Als Fehler wird mir ausgeworfen: System.Windows.Markup.XamlParseException: ""Binding" kann nicht für die Eigenschaft "Text" vom Typ "MyTextbox" festgelegt werden. "Binding" kann nur für eine "DependencyProperty" eines "DependencyObject" festgelegt werden."


    VB.NET-Quellcode

    1. Public Class Person
    2. Public Property Person As New myTextbox With {.Text = FirstName}
    3. Public Property FirstName As String = ""
    4. End Class


    Quellcode

    1. <DataGrid x:Name="dgMain" Width="Auto" AutoGenerateColumns="True" ItemsSource="{Binding Path=PersonsList}">
    2. <DataGrid.Columns>
    3. <DataGridTextColumn Binding="{Binding FirstName}" Header="FirstName"/>
    4. <DataGridTemplateColumn>
    5. <DataGridTemplateColumn.CellTemplate>
    6. <DataTemplate>
    7. <local:MyTextbox Text=""/>
    8. </DataTemplate>
    9. </DataGridTemplateColumn.CellTemplate>
    10. </DataGridTemplateColumn>
    11. </DataGrid.Columns>
    12. </DataGrid>


    Wie gesagt: Die Spalte mit dem Vornamen ist richtig gebunden und zeigt auch wie gewünscht den Inhalt an. Dieser Inhalt müsste für die Eigenschaft Text in der Spalte mit dem Control MyTextbox verwendet werden. Dies geht leider nicht.

    Ich komme hier irgendwie nicht weiter.

    Ich würde mich freuen, wenn jemand helfen könnte.

    Lieben Dank.
    Chris
    Hallo und willkommen im Forum

    Hotdogxxxx schrieb:

    Hierzu habe ich eine Klasse erstellt, welches mein UserControl beinhaltet.

    Da liegt dein denkfehler. Die Klasse soll nicht das Control enthalten sondern die Daten. Als den Vornamen.

    VB.NET-Quellcode

    1. Public Class Person
    2. Public Property VesselName As String
    3. Public Property FirstName As String = ""
    4. End Class


    Im UI bestimmst du dann erst wie es aussehen soll, also eben dein UserControl.

    Wenn du die Spalten manuell angeben willst dann so:

    XML-Quellcode

    1. <DataGrid x:Name="dgMain" Width="Auto" AutoGenerateColumns="False" ItemsSource="{Binding Path=PersonsList}">
    2. <DataGrid.Columns>
    3. <DataGridTextColumn Binding="{Binding FirstName}" Header="FirstName"/>
    4. <DataGridTemplateColumn Header="MeinHeader">
    5. <DataGridTemplateColumn.CellTemplate>
    6. <DataTemplate>
    7. <local:MyTextbox Text="{Binding VesselName}"/>
    8. </DataTemplate>
    9. </DataGridTemplateColumn.CellTemplate>
    10. </DataGridTemplateColumn>
    11. </DataGrid.Columns>
    12. </DataGrid>


    Du sagst das die Column mit dem Control MyTextBox gerendert werden soll und Bindest deine Property an die Text-eigenschaft deines Controls. (Vorausgesetzt das es eine DependencyProperty ist, was ich eben nicht glaube)
    Siehe diesbezüglich Kapitel 2.5.1 - DependecyProperties meiner Tutorialreihe. Dann klappt es auch mit dem Binding.

    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. ##

    Erstmal vielen Dank Sascha! Ich habe mir dein Tutorial angesehen und erstmal deinen Kanal abonniert. :thumbsup:

    Du hast Recht. Die Eigenschaft Text in MyTextbox war keine DependencyProperties sondern hat den Wert einfach an die eigentliche Text Eigenschaft der dahinterstehenden Textbox weitergereicht.
    Ich habe dir mal den Code wie er vorher war beigefügt.

    VB.NET-Quellcode

    1. Public Property Text As String
    2. Get
    3. Return tbxMain.Text
    4. End Get
    5. Set(ByVal value As String)
    6. tbxMain.Text = value
    7. End Set
    8. End Property


    Ich habe nun den Code nach deinem Tutorial (soweit verstanden) auf wie folgt abgeändert.

    VB.NET-Quellcode

    1. Public Class Person
    2. Public Property Text As String
    3. Get
    4. Return CType(GetValue(TextProperty), String)
    5. End Get
    6. Set(ByVal value As String)
    7. debug.Writeline("Name: " & Value)
    8. SetValue(TextProperty, value)
    9. tbxMain.Text = value
    10. End Set
    11. End Property
    12. Public Shared ReadOnly TextProperty As DependencyProperty =
    13. DependencyProperty.Register("Text",
    14. GetType(String), GetType(Person))
    15. End Class


    Nun wird zwar kein Fehler mehr beim Starten angezeigt und ich kann den Code normal ausfüllen aber die Spalte mit myTextbox zeigt noch immer nicht den FirstName an.

    Irgendwie scheint da bei Text nichts anzukommen.

    :cursing:
    OK, dann hast du mein Kapitel Falsch verstanden. Der Setter des Properties bleibt bei einem DependencyProperty so wie er ist. Dort wird nichts gesetzt.
    Also: tbxMain.Text = value mal raus.

    Stattdessen Bindest du im XAML deines UserControls auf dieses DependencyProperty. Jetzt kann es ja gebunden werden.

    Und dann eben im DataGrid wie gehabt binden - aber das hast du ja bereits.

    Der Grund warum man in den Setter nicht eingreifen soll wird auch im Kapitel behandelt.
    Der Grund warum man ein DependencyProperty macht ist ja Bindingunterstützung, insofern sollte man dann auch mit Binding arbeiten.

    Falls du nicht zurechtkommst sag bescheid.

    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 Sascha,

    irgendwie funktioniert das nicht. Ich glaube es liegt daran, dass es mehr verschachtelt ist als du denkst. Ich muss dazu sagen, dass ich das erste mal mit WPF arbeite und daher nicht wirklich weiß was ich tue... 8o

    Ich bin dir für deine Hilfe unendlich dankbar.
    Ich möchte mich aber nochmal erklären in der Hoffnung, dass wir das Problem gelöst bekommen.

    Ich möchte auf einer Page ein DataGrid einfügen. Dieses DataGrid ist mit einer Klasse verbunden von der es die Daten bezieht. Wie du gesagt hast habe ich hier nur noch Daten stehen und keine Controls. Die Bindung funktioniert und die Daten werden in dem Datengrid angezeigt.
    Die Daten sollen aber nicht einfach angezeigt werden, sondern die Daten sollen genutzt werden, um eigene Textboxen zu befüllen, die wiederum in das DataGrid über DataGridTemplateColumn hinzugefügt werden.

    Ein Datensatz meiner Klasse beinhaltet als Beispiel den Namen "Sascha". Dieser Name soll dann in die jeweile Zeile des Datensatzes in die Spalte bestehend auf meinen Textboxen in die Eigenschaft Text eingefügt werden. Wenn ich im DatenGrid in diese Textboxen manuell schreibe funktioniert es zu 100%. Aber ich schaffe es eben nicht, die Daten aus dem Datensatz automatisch in diese Textboxen zu füllen.

    Diese eigenen Textboxen haben eine Text Eigenschaft. Diese habe ich entsprechend deines Tutorials angepasst. Dadurch wird beim Binden zwar kein Fehler mehr ausgeworfen, aber es wird noch immer kein Name übertragen. Wenn ich also mit debug.Writeline den Value von Text auswerfen lasse ist dieser leer.

    Diese eigenen Textboxen ich nenne sie mal "MyTbx" beinhalten aber wiederum neben anderen Controls auch eine weitere Textbox mit dem Namen "TbxMain". Somit war bisher die Aufgabe der Property Text von MyTbx die Daten einfach von und nach TbxMain.Text weiterzureichen. Von dieser TbxMain werden die Daten dann verarbeitet was wiederum Auswirkungen auf Style, TextChange-Event usw. hat. Diese tbxMain wird an unzähligen Stellen der Applikation verwendet und ich kann diese nicht so einfach umbauen, ohne die gesamte Funktionalität zu gefärden.

    Gibt es neben Binden nicht eine andere Möglichkeit, dass der Name z.b. "Sascha" des Datensatzes (Klasse) als String in die Eigenschaft Text der MyTbx eingefügt wird. Hilft hier vielleicht ein Converter?
    Hallo

    Du brauchst keine Converter oder sonst was.

    Hotdogxxxx schrieb:

    Wenn ich also mit debug.Writeline den Value von Text auswerfen lasse ist dieser leer.

    Du hast das Kapitel "Dependency Property" nicht verstanden. Im Setter passiert auch nix beim Binding. Der Setter ist bei einem Dependency Property nicht dafür da. Da kann also keine Debugausgabe erfolgen. Das ist also schon alles richtig so.

    Hotdogxxxx schrieb:

    Diese eigenen Textboxen ich nenne sie mal "MyTbx" beinhalten aber wiederum neben anderen Controls auch eine weitere Textbox mit dem Namen "TbxMain". Somit war bisher die Aufgabe der Property Text von MyTbx die Daten einfach von und nach TbxMain.Text weiterzureichen. Von dieser TbxMain werden die Daten dann verarbeitet was wiederum Auswirkungen auf Style, TextChange-Event usw. hat. Diese tbxMain wird an unzähligen Stellen der Applikation verwendet und ich kann diese nicht so einfach umbauen, ohne die gesamte Funktionalität zu gefärden.

    Uiuiui, da ist aber etwas ganz verquer an der Architektur. UI sollte nie für die Weiterverarbeitung von Daten zuständig sein. Wozu auch, ich habe eine Klasse wo die Daten drinnen sind, diese soll sollche Dinge auch erledigen.
    Aber egal.

    Hier ein kleines Demo genau so wie du es willst, und genau wie ich es auch beschrieben habe. Wichtig ist das Binding innerhalb der Usercontrols.

    Grüße
    Sascha
    Dateien
    • Dp_Demo.zip

      (30,25 kB, 97 mal heruntergeladen, zuletzt: )
    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. ##

    Uiuiui, da ist aber etwas ganz verquer an der Architektur.

    Du hast sicherlich recht. Ich hatte mich aber auch falsch ausgedrückt. In den Controls wird nicht selbst gerechnet, aber es verweist bei TextChanged, LostFocus usw auf die entsprechenden Module. Dennoch wie gesagt ich bin weder Professionell noch habe ich das Konzept mit Binding und allem noch nicht so ganz verstanden. Ich werde mir aber deine Tutorials ansehen und sicherlich viel lernen. Hierfor schon mal Danke.

    Vielen Dank auch für deine Hilfe. Wirklich Top! Dank deines Anhangs habe ich verstanden, wo mein Fehler lag und habe die Kette durch die Controls entsprechend ergänzt.
    Nun funktioniert es wie gewollt. Ich makiere es daher als Solved. Danke!!!