Binding mit Parametern

  • WPF

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von Johannes.

    Binding mit Parametern

    Hallo miteinander!

    Ist es möglich, im Binding einen Parameter zu übergeben?

    Ich habe eine TextBox in einem UserControl.
    Im CodeBehind gibt es DependencyProperty rs As Recordset und FeldName As String.

    Das Funktioniert: Text="{Binding rs.Fields[Wohnort].Value, ElementName=userControl ...}"

    Jetzt würde ich gern "Wohnort" durch die Variable FeldName ersetzen, also eine Art "Bindig im Binding".
    Im CodeBehind sollte das kein Problem darstellen, dort kann ich mir ja solche Zeichenketten zusammenbauen, in XAML auch?

    Liebe Grüße und
    Vielen Dank!
    Hallo

    Ja, das ist möglich mit der Eigenschaft Parameter.

    Auch hier kann ich wieder auf mein Tutorial verweisen:
    Kapitel 2.1.4.1 - Binding

    Man muss hier nur bedenken das die Eigenschaft Parameter kein Binding unterstützt, du kannst also einen String mit übergeben aber du kannst nicht auf etwas Binden.
    In deinem Fall würde ich dann weiterlesen...
    Lese dir auf jeden Fall das Folgekapitel Converter auch durch, das ist mehr als interressant und dürfte für deinen aktuellen Fall sicher die lösung sein, muss aber nicht, du lässt leider nicht genug Informationen hier um eine wirklich gute Lösung für dein Vorhaben vorschlagen zu können.

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

    Danke für die schnelle Antwort!
    Ich werde mir also dein Tutorial "reinziehen" und alles lesen, was ich über Parameter und Converter lesen kann.

    Ich dachte eigentlich, meine Frage wäre kurz und deutlich, offensichtlich war sie zu Kurz.

    Ich möchte in einer Datenbankanwendung ein eigenes userControl mehrfach verwenden. Das userControl hat ein Label, eine Textbox, eine Combobox und eine Schaltfläche mit der ich die Combobox und Textbox ein und ausblende. Die Combobox soll jeweils die Datensatzsuche über das jeweilige Feld starten. Das Recordset liegt im Window und wird über DataContext abgerufen.
    Mit den DependencyProperty Caption und FieldName kann ich im Fensterdesigner schon mal das Label umbenennen, doch den FeldName krieg ich einfach nicht in die Textbox hinein.

    Die Datenbindung in XAML funktioniert mit dieser Zeile: "Text="{Binding rs.Fields[Wohnort].Value}"
    Doch dann muss ich für Wohnort, Vorname, Nachname, Straße, PLZ... jeweils ein eigenes UserControl schreiben und dann kann ich mir den Spaß wohl schenken und gleich im Fenster programmieren.
    Ich würde also lieber so etwas wie "Text={Binding rs.Fields[{FeldName}].Value}" schreiben.
    Das funktioniert so aber (noch?) nicht.
    Ich habe schon versucht im CodeBehind das Binding zu setzen, doch da bin ich im Moment auch zu blöd.

    Versuch in new oder loaded

    VB.NET-Quellcode

    1. Private Sub userControl_Loaded ....
    2. Dim bnd as New Binding
    3. Dim Path As String = "rs.Fields[" + FieldName + "].Value"
    4. bnd.Path = New PropertyPath(Path)
    5. Me.tbValue.SetBinding(TextBlock.TextProperty, bnd)
    6. end sub



    Mit diesem Code bekomme ich aber (noch) keine funktionierende Bindung hin, egal ob ich "Vorname" in die Eckigen Klammern schreibe oder wie im Code zusammensetze.

    Auf jeden Fall Vielen Dank für Deine Mühen und die Schnellen Antworten!

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

    Hallo

    OK, Ich verstehe nun dein Anliegen. Du willst im ein Usercontrol in welchem du Daten editieren kann wobei du willst das die Labels nach dem feldnamen der DB beschriftet werden. (wennich das richtig verstanden habe.

    Du erstellst also ein Usercontrol und verpasst diesem ein korrektes(!) neues DependencyProperty (nennen wir es mal Caption). Ein DependencyProperty ist Bindbar.
    Auch hierzu habe ich ein Kapitel.

    Teilweise hast du das ja hinbekommen.

    Johannes schrieb:

    doch den FeldName krieg ich einfach nicht in die Textbox hinein.

    Da sich der Datenkontext ja verändern könte empfehle ich hier ein Binding mittels FindAncestor da klappt dann sicher und auch immer.

    Solltest du nicht zurecht kommen kann ich dir gerne ein kleines Beispiel erstellen.

    PS: Bitte verwende codeTags in deinem Beiträgen damit Code vernünftig zu lesen ist. Ich korrigiere das jetzt mal.

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

    Hm,
    irgendwie verstehen wir uns noch nicht so ganz richtig.
    Vielleicht drücke ich mich nicht korrekt aus.

    Ein RecordSet ist eine Collection of Collection of Object
    Das macht das Verständnis jetzt nicht wirklich leichter, also lasse ich mal das RecordSet weg.
    Fields ist eine Auflistung von Field und Field kann man sich als Klasse mit Value, Name, OldValue u.s.w. vorstellen.

    Die Propery "Caption" an mein Label zu binden ist ja ganz einfach: DependencyProperty und den Label.Content binden - "ferdsch".

    Mein Problem ist ein dynamischer Parameter in der Bindung-Zeichenfolge im XAML (oder im CodeBehind - was auch immer funktioniert).
    mit "Fields[1].Value" oder "Fields[Vorname].Value" kann ich binden,
    doch wenn ich den Index "1" oder "Vorname" erst in meiner Anwendung festlegen will, dann klappt das nicht - weil ich zu blöd bin - vermutlich.

    Im CodeBind müsste das eigentlich funktionieren, da ich mir dort meine Zeichenfolge einfach zusammensetzen kann, hat aber auch (noch?) nicht geklappt.
    Da mache ich einen Grundsätzlichen Fehler, denn die selbe Textzeile die im XAML funktioniert, funktioniert hier (so) nicht. (siehe Code oben)

    Hier hat jemand ein ähnliches (wenn auch völlig anderes Problem) für mich zu kompliziert - gelöste
    https://andydunkel.net/2019/12/03/wpf-databinding-converterparameter-und-property-in-einem-usercontrol/

    Also noch einmal anders: Ich möchte eine IndexVariable (Betonung auf Variable!) in den XAML Binding-Code einfügen.
    So, jetzt weiß ich wirklich nicht, wie ich das noch anders ausdürcken kann.

    Trotzdem Vielen Dank
    und Entschuldige, wenn ich dir "Deine Zeit klaue"!
    Hallo

    OK, jetzt verstehe ich es in etwa. Ist aber schwer zu erklären so das es für dich verständlich wird.

    Mein vorschlag.
    Beu ein kleines Beispiel in welchem du ein Recordset simulierst und dein Usercontrol drinnen hast.
    Ich bau dir das dann gerne so um das es funktioniet und schreibe dir hier rein was und warum es geändert wurde.

    Ich denke so wird es für dich (anhand deines Fallbeispiels) am ehestem verständlich.

    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,
    das ist ein ziemliches Angebot von Dir - Dank Vielmals!
    dropbox.com/s/kke1vxt4u1g9kku/…ingWithParameter.zip?dl=0

    Hier im Beispiel hat das DBUserControl schon ein DependencyProperty "FeldType" vom Typ Enum Felder Vorname=0 Zuname=1 End Enum
    (in einem echten Recordset könnte man "Vorname" und "Zuname" oder 0 und 1 als Index verwenden)

    Jetzt müsste ich nur noch diesen "FeldType" in das DataBinding verschachteln.
    rsX[FeldType].Value


    myDAO - eine ziemlich "hingerotzte" Datenbank-Klasse, die so etwas ähniches macht, wie ein Recordset.
    Aber wirklich nur, um mal ganz schnell eine Demo zusammen zu frickeln.
    Ich kann z.B. nicht mit dem Feldnamen inizieren ("Vorname") sondern nur mit der Indexnummer 0,1...
    Mit dem Enum "Felder" sieht es dann so ähnlich aus.

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Imports System.ComponentModel
    3. Public Enum Felder
    4. Vorname = 0
    5. Zuname = 1
    6. End Enum
    7. Public Class myDAO
    8. Implements INotifyPropertyChanged
    9. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    10. Public rs As Recordset
    11. Public Sub New()
    12. rs = New Recordset
    13. Dim f As New Fields
    14. f.Add(New Field("Vorname", "Thomas"))
    15. f.Add(New Field("Zuname", "Meier"))
    16. rs.Add(f)
    17. f = New Fields
    18. f.Add(New Field("Vorname", "Susanne"))
    19. f.Add(New Field("Zuname", "Schönberg"))
    20. rs.Add(f)
    21. End Sub
    22. End Class
    23. Public Class Field
    24. Implements INotifyPropertyChanged
    25. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    26. Private _Name As String
    27. Private _Value As String
    28. Public Property Name() As String
    29. Get
    30. Return _Name
    31. End Get
    32. Set(ByVal value As String)
    33. _Name = value
    34. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Field"))
    35. End Set
    36. End Property
    37. Public Property Value() As String
    38. Get
    39. Return _Value
    40. End Get
    41. Set(ByVal value As String)
    42. _Value = value
    43. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Field"))
    44. End Set
    45. End Property
    46. Public Sub New(Optional FeldName As String = "", Optional FeldValue As String = "")
    47. Name = FeldName
    48. Value = FeldValue
    49. End Sub
    50. End Class
    51. Public Class Fields
    52. Inherits ObservableCollection(Of Field)
    53. End Class
    54. Public Class Recordset
    55. Inherits ObservableCollection(Of Fields)
    56. End Class



    Das DBUserControl
    DBUserControl.xaml

    XML-Quellcode

    1. <UserControl x:Name="userControl" x:Class="DBUserControl"
    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:DemoBindingWithParameter"
    7. mc:Ignorable="d" d:DesignWidth="800" Height="55.418">
    8. <StackPanel Orientation="Horizontal" >
    9. <Label x:Name="label" Content="{Binding Caption, ElementName=userControl, FallbackValue='Label: ', Mode=TwoWay, NotifyOnSourceUpdated=True, TargetNullValue='Label: ', UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" VerticalAlignment="Center" Height="29" Width="Auto" Margin="0,10,0,16"/>
    10. <TextBox x:Name="textBox" HorizontalAlignment="Left" Text="{Binding rsX[0].Value, FallbackValue=Bindung unbekannt, NotifyOnSourceUpdated=True, TargetNullValue=Bindung unbekannt}" VerticalAlignment="Center" Height="23" Width="Auto" />
    11. </StackPanel>
    12. </UserControl>


    und das dazugehörige CodeBehind
    DBUserControl.xaml.vb

    VB.NET-Quellcode

    1. Public Class DBUserControl
    2. Public Property Caption As String
    3. Get
    4. Return GetValue(CaptionProperty)
    5. End Get
    6. Set(ByVal value As String)
    7. SetValue(CaptionProperty, value)
    8. End Set
    9. End Property
    10. Public Shared ReadOnly CaptionProperty As DependencyProperty =
    11. DependencyProperty.Register("Caption",
    12. GetType(String), GetType(DBUserControl),
    13. New PropertyMetadata(Nothing))
    14. Public Property FieldType As Felder
    15. Get
    16. Return GetValue(FieldTypeProperty)
    17. End Get
    18. Set(ByVal value As Felder)
    19. SetValue(FieldTypeProperty, value)
    20. End Set
    21. End Property
    22. Public Shared ReadOnly FieldTypeProperty As DependencyProperty =
    23. DependencyProperty.Register("FieldType",
    24. GetType(Felder), GetType(DBUserControl),
    25. New PropertyMetadata(Nothing))
    26. End Class



    In der MainWindow habe ich etwas wild herumprobiert

    MainWindow.xaml

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:DemoBindingWithParameter"
    7. mc:Ignorable="d"
    8. Title="MainWindow" Height="450" Width="800">
    9. <Grid>
    10. <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="262,78,0,0" TextWrapping="Wrap" Text="{Binding rs.Item[0].Item[0].Value, FallbackValue=Max, NotifyOnSourceUpdated=True}" VerticalAlignment="Top" Width="120"/>
    11. <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="531,78,0,0" VerticalAlignment="Top" Width="75"/>
    12. <TextBox x:Name="textBox2" HorizontalAlignment="Left" Height="23" Margin="262,122,0,0" TextWrapping="Wrap" Text="{Binding rs.Item[0].Item[1].Value, FallbackValue=Muster}" VerticalAlignment="Top" Width="120"/>
    13. <Label x:Name="label" Content="{Binding rs.Item[0].Item[0].Name, FallbackValue='Label: ', Mode=OneWay, NotifyOnSourceUpdated=True}" HorizontalAlignment="Left" Margin="88,78,0,0" VerticalAlignment="Top"/>
    14. <Label x:Name="label1" Content="{Binding rs.Item[0].Item[1].Name, FallbackValue='Label: ', Mode=OneWay}" HorizontalAlignment="Left" Margin="88,119,0,0" VerticalAlignment="Top"/>
    15. <TextBox x:Name="textBox3" HorizontalAlignment="Left" Height="23" Margin="262,171,0,0" TextWrapping="Wrap" Text="{Binding rsX.Item[0].Value, FallbackValue=Max, NotifyOnSourceUpdated=True}" VerticalAlignment="Top" Width="120"/>
    16. <Button x:Name="button2" Content="next" HorizontalAlignment="Left" Margin="531,170,0,0" VerticalAlignment="Top" Width="75"/>
    17. <TextBox x:Name="textBox4" HorizontalAlignment="Left" Height="23" Margin="262,214,0,0" TextWrapping="Wrap" Text="{Binding rsX[1].Value, FallbackValue=Muster}" VerticalAlignment="Top" Width="120"/>
    18. <Label x:Name="label3" Content="{Binding rs.Item[0].Item[0].Name, FallbackValue='Label: ', Mode=OneWay, NotifyOnSourceUpdated=True}" HorizontalAlignment="Left" Margin="88,172,0,0" VerticalAlignment="Top"/>
    19. <Label x:Name="label4" Content="{Binding rs.Item[0].Item[1].Name, FallbackValue='Label: ', Mode=OneWay}" HorizontalAlignment="Left" Margin="88,210,0,0" VerticalAlignment="Top"/>
    20. <local:DBUserControl HorizontalAlignment="Left" Height="43" Margin="88,272,0,0" VerticalAlignment="Top" Width="474" Caption="Familienname: " FieldType="Zuname"/>
    21. </Grid>
    22. </Window>



    und der CodeBehind
    MainWindow.xaml.vb

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Class MainWindow
    3. Implements INotifyPropertyChanged
    4. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    5. Private DB As New myDAO
    6. Public Property rs() As Recordset
    7. Get
    8. Return DB.rs
    9. End Get
    10. Set(ByVal value As Recordset)
    11. DB.rs = value
    12. End Set
    13. End Property
    14. Private _rsIndex As Integer 'Default = 0
    15. Public Property rsIndex() As Integer
    16. Get
    17. Return _rsIndex
    18. End Get
    19. Set(ByVal value As Integer)
    20. If (value < 0) Or (value > DB.rs.Count - 1) Then
    21. MsgBox("Index außerhalb der Gültigkeit")
    22. Else
    23. _rsIndex = value
    24. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("rsX"))
    25. End If
    26. End Set
    27. End Property
    28. Public Property rsX() As Fields
    29. Get
    30. Return DB.rs(rsIndex)
    31. End Get
    32. Set(ByVal value As Fields)
    33. DB.rs(rsIndex) = value
    34. End Set
    35. End Property
    36. Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
    37. MsgBox(rs.Item(0).Item(0).Name & ": " & rs.Item(0).Item(0).Value)
    38. MsgBox(rs(1)(0).Name & ": " & rs(1)(0).Value)
    39. MsgBox(rsX(Felder.Vorname).Name & ": " & rsX(Felder.Vorname).Value)
    40. Me.rsIndex = 1
    41. MsgBox(rsX(Felder.Vorname).Name & ": " & rsX(Felder.Vorname).Value)
    42. End Sub
    43. Public Sub New()
    44. ' Dieser Aufruf ist für den Designer erforderlich.
    45. Me.DataContext = Me
    46. InitializeComponent()
    47. ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
    48. End Sub
    49. Private Sub button2_Click(sender As Object, e As RoutedEventArgs) Handles button2.Click
    50. rsIndex = rsIndex + 1
    51. End Sub
    52. End Class
    Hallo

    OK, ich schau mir das mal an.
    Nur als Tipp. Dateien mittels externen Anbietern zu übermitteln ist hier nicht gerne gesehen. Aus dem Grund weil wenn die Datei nicht mehr verfügbar ist, kann niemand mehr etwas mit dem Thread anfangen und man will der Nachwelt ja was hinterlassen.

    In Zukunft bitte "Erweiterte Antwort" und dort kannst du z.b. eine ZIP (bereinigt - also ohne Bin Ordner) hochladen.

    Grüße
    Sascha

    Edit: @Johannes ich blick da jetzt irgendwie noch immer nicht ganz durch was du genau erreichen willst. Sorry, ich steh am schlauch. Willst du nun hier das statt "Familienname" Zuname steht oder wie? Bitte sag mir kurz WAS du an WAS Binden willst.



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

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

    Hallo Sascha,

    die Idee ist, ein DBControl zu basteln (später noch 3 oder 4 andere), mit denen ich dann in der eigentlichen Anwendung die verschiedensten Datenfelder abbilde.

    Das Fenster würde dann also 7 DBText-Contrls haben und 2 DBBoolean und 5 DBSearchableText und ein DBButtons enthalten.

    Und in jedem Control lege ich nur noch eine andere Datenbindung, genauer einen anderen Feldindex fest.
    Das geht aber nur, wenn ich den Feldinex nicht schon im DBControl fest einprogrammieren muss.


    Was für mich irgendwie keinen Sinn ergibt ist, dass ich für jedes Datenbankfeld ein eigenes Control erstellen soll, dann bin ich schneller, wenn ich gleich alles "zu Fuß" im Fenster erledige.

    Ich würde das auch im CodeBehind programmieren, hab da aber noch einen Fehler drin

    VB.NET-Quellcode

    1. Dim sbind As String
    2. sbind = "{Binding rsX[" & FieldType & "].Value}"
    3. Dim bnd As New Binding
    4. bnd.Path = New PropertyPath(sbind)
    5. textBox.SetBinding(TextBox.TextProperty, bnd)


    sbind hat jetzt den Text "{Binding rsX[1].Value}", also exakt das, was ich im xaml auch geschrieben habe, hat aber (noch) nicht funktioniert.



    Danke nochmals für deine Bemühungen!
    Johannes
    Dateien
    Hab's jetzt hinbekommen

    VB.NET-Quellcode

    1. Dim sbind As String
    2. sbind = "rsX[" & FieldType & "].Value"
    3. Dim bnd As New Binding()
    4. bnd.Path = New PropertyPath(sbind)
    5. bnd.FallbackValue = "Bindung unbekannt"
    6. bnd.NotifyOnSourceUpdated = True
    7. bnd.TargetNullValue = "Bindung unbekannt"
    8. DBtextBox.SetBinding(TextBox.TextProperty, bnd)


    In new ProperyPath darf der String keine geschweiften Klammern und kein "Binding" enthalten

    Den Code musste ich im "Loaded" Event des Controls einbinden, im New() war der FeldIndex (FieldType) noch nicht verfügbar.

    Und nun die Frage vom Anfang: Wäre das auch direkt im XAML gegangen?

    Liebe Grüße
    Johannes

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

    Hallo Johannes

    OK, ich habe viel zu kompliziert gedacht. Hier geht es ja um wirklich simples Binding.

    Ich will nicht kritisieren und dich nicht runtermachen - bitte nicht falsch verstehen - ich will nur helfen. Deshalb ein paar Punkte damit du in naher Zukunft nicht den spass an der WPF verlierst.
    Gewöhne dir zum einen Binding an, vergiss CodeBehind. Auch für Button-Clicks arbeite mit Commands (siehe mein Tutorial). Ich weis nicht warum du mit DAO rumhantierst wenn es doch viel bessere Methoden gibt aber gut, das kann evtl. einen Grund haben.

    Vergiss den Designer. sowas hier:


    Da bekommt man Augenkrebs. Das passiert wenn man die Elemente mit dem Designer draufzieht. Wenn man aus Winforms kommt ist es auch logisch wenn man so versucht zu arbeiten. aber die WPF ist etwas anders aufgebaut. Viel besser und auf dauer auch VIEL einfacher geht es wenn man den Editor benutzt. Warum und weshalb erkläre ich (ich glaube das zweite Kapitel war es) in meinem Tutorial.

    Sonst hattest du aber den völlig richtigen ansatz und warst ja auch fast am Ziel.
    Ich habe dir das nun mit reinem Binding umgebaut und den FieldType nun mittels Enumerator gemacht. Ich habe dir auch die möglichkeit eingebaut das dein Usercontrol nun auf den Datentyp (FieldType) reagiert und sich dementsprechend ändert je nachdem was für ein FieldType angegeben wurde. Ob per XAML direkt oder per Binding beibt dir dann überlassen.



    So bist du mit diesem Control vollig frei und kannst es verwenden für was du willst.

    Anbei auch das Projekt.

    Eines noch am Rande:

    VB.NET-Quellcode

    1. Public Property Name() As String
    2. Get
    3. Return _Name
    4. End Get
    5. Set(ByVal value As String)
    6. _Name = value
    7. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Field"))
    8. End Set
    9. End Property

    Warum Propertychanged auf "Field"? Das bringt dir nichts. Du kannst nur PropertyNamen als PropertychangedEventArg angeben. Willst du im View ein Refresh der ganzen View bewerkstelligen dann übergebe als EventArg ein "Nothing".

    Falls du Fragen hast melde dich einfach. Wie gesagt, du bist am richtigen Weg und willst ja anscheinend auch Binding verwenden. Bitte zieh es auch durch. CodeBehind bricht dir auf dauer in der WPF das Bein. Nur gut gemeint. Bin gerne zur Unterstützung da ;)

    Grüße
    Sascha
    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. ##

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

    Hallo Sascha,
    da zieh ich mal "alle Hüte", diesen Code hätte ich in Woche so nicht hinbekommen.
    Da fehlt mir einfach der Ansatz, um überhaupt zu wissen, welche Frage ich stellen sollte.

    Ich hatte früher mal mit C / C++ Pascal und Delphi angefangen (nur so als Hobby und Interesse) und bin oft an grundlegenden Techniken abgestorben.
    Ich wollte z.B. einen Vokabeltrainer Entwickeln und musste damals noch dann den ganzen Serialisierungsprozess von Hand entwickeln so mit fprintf u.s.w. (String oder doch Objekte und wie bekomme ich die aus einer Datei wieder heraus?) Heute könnte ich einen XML-Parser nehmen. Bei C/C++ muss(te) man Speicherplatz noch anfordern und später auch wieder "ordentlich aufräumen", an solchem Zeug kann man als Anfänger verzweifeln. Als mir dann eine Datenbank in die Hände fiel, hatte ich meine erste Anwendung in weniger als einer Stunde zusammen geklickt und bin dann eben bei Datenbanken hängen geblieben.
    Seit dem bin ich wohl eher ein "Button-Click Programmierer" ^^ (auch wenn das deinen Augen weh tut ^^ )

    Ich versuche jetzt erst einmal zu verstehen, was du da alles geschrieben hast.

    VB.NET-Quellcode

    1. Public Enum enumFieldType
    2. [String] = 0
    3. [Date] = 1
    4. [Bool] = 2
    5. End Enum

    Auf die Idee, Variablentypen mit [] zu "schützen" wäre ich auch nicht gekommen, hab das leider noch nirgends gesehen. (aber ich kenne auch nicht das ganze Internet ;) )

    In deinem Tutorial beschreibst du oft FindAncestor. Was ist der Vorteil gegenüber einem Binding an DataContext, oder Element?
    Verstehe ich das richtg, FindAncestor sucht erst zur Laufzeit nach einer passenden Variablen (nach oben). In meinem User Control ist das doch schon bekannt, oder ?

    Warum DAO?
    Nun auf einem Desktop eine Web-Datenbank mit lokalem Server, das ist mit Kanonen auf Spatzen schießen und für viele Anwender zu kompliziert.
    DAO oder ADO? Das macht für mich keinen großen Unterschied, wenn ich bei dem alten mdb-Format bleiben will, mit ADO könnte ich das System leichter wechseln, aber wer will das schon.
    Solange Leute ihre Firmendaten Excel anvertrauen, solange kann ich auch mdb verwenden.

    ADO.Net mit DataSet
    Nun bisher haben mich die entsprechenden Beispielprogramme weder in Büchern noch im Internet überzeugt - hatte ich wohl einfach noch nicht das richtige.
    In allen Beispielen wurde die gesamte Datenbank in der Anwendung praktisch noch einmal neu programmiert.
    Jede Tabelle mit jedem Feld mit Name, Typ, FieldSize und Beschränkungen wurde im DataSet explizit noch einmal angelegt. Von einer Änderung an der Datenbank erfährt die Anwendung nichts und eine Änderung in der Anwendung führt erst beim Schreiben der Daten zu (hoffentlich auffangbaren) Fehlern.

    Es ist nicht so, dass ich nichts lernen will, aber Bergsteigen fängt man ja auch nicht am Mount Everest an.
    Liebe Grüße
    Johannes

    Ich hänge noch mal meine Laien-Version an. "Für die Nachwelt"
    Auch wenn es mir auf die Schnelle nicht gelungen war das Binding direkt an die Listbox zu setzen und ich einen HilfsButten zwischenschalte, sowas passiert, wenn man nachts halb Eins noch schnell was ausprobieren will.
    Dateien

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

    Hallöle Johannes

    Johannes schrieb:

    Auf die Idee, Variablentypen mit [] zu "schützen" wäre ich auch nicht gekommen, hab das leider noch nirgends gesehen.

    Ja, das kann man in Vb.Net machen wenn man z.b. eine Variable mit einem "reservierten" Wort versehen will. String ist ein Datentyp und kann somit nicht als Veriablenname oder Enumerator verwendet werden. Die Eckigen Klammern veranlassen den Compiler dazu dir das durchgehen zu lassen. ;)

    Johannes schrieb:

    In deinem Tutorial beschreibst du oft FindAncestor. Was ist der Vorteil gegenüber einem Binding an DataContext, oder Element?

    In deinem Fall kannst du nicht an einen DatenKontext Binden da dieser sich ja ändern könnte. Ein UserControl erbt immer den DatenKontext von dem Element in welchem es sich verbindet (um genau zu sein jedes FrameworkElement, also jedes Control in der WPF). Klar, jetzt kannst du deinem UserControl einen Name verpassen. Unschön. Erstens kann es sein das du es mal unbenennen willst und denkst nicht daran das du irgendwo ein Binding hast welches damit im Eimer ist und wunderst dich warum gewisse Dinge plötzlich nicht mehr funktionieren. Kann einem viel Zeit kosten. Und zweitens sollte man (ist einfach zum Debuggen und bei Bindingfehlern viel schlne in der Ausgabe zu lesen) keine Controlnamen (wenn man schon welche vergibt) doppelt vergeben. Hast du nun im Window drei von deinen UserControls dann hast du drei mal den gleichen Namen da du Ihn ja im UserControl selbst ganz oben definiert hast. Jetzt kommst du evtl. auf die Idee ihn von Außen zu setzen mit <UserControl Name=neuerName..../> und schon funktioniert dein Binding innerhalb des Controls nicht mehr. Siehe weiter oben im Text.

    Find Ancestor such im EloementTree nach oben nach einem Element eines gewissen Typs. In deinem Fall nach deinem UserControl. Es gelangt zum Grid -> Ne ist nicht das -> dann zum UserControl - wird fündig und holt sich dirt das Binding - je nachdem auf was du Bindest. Du kannst also sichergehen das du hier "save" bist. Und... du hast Compilerprüfung. änderst du den Typen des UserControls weil du die Klasse umbenennst dann schlägt der Compiler dir das um die Ohren und du siehst sofort in der Fehlerlist das ein Binding nicht mehr funktioniert und kannst es ausbessern. Ich versuche IMMER beim Programmieren auch ein Stück weit mich selbst zu "kontrollieren", denn jeder macht Fehler und denkt z.b. an gewisse Abhängigkeiten nicht und schon funktionieren Programmteile nicht mehr die vor ein paar Tagen noch problemlos funktioniert haben. Das will ich vermeiden.

    Johannes schrieb:

    Nun auf einem Desktop eine Web-Datenbank mit lokalem Server, das ist mit Kanonen auf Spatzen schießen und für viele Anwender zu kompliziert.

    Ja, es war nur eine Frage. Locale Datenbanken gibt es ja auch genug und die kann man mit EntityFramework auch verwenden, da muss man nicht mdit so Krücken herumhantieren ohne Compileprüfung und SQL Strings in welchen sich zig Fehler einschleichen können weil eben keine Compilerprüfung vorhanden ist. Dann gibt es (ich weis nicht ob es eine Mehranwendersoftware ist) noch die möglichkeit einfach in XML zu serialisieren was auch in den meißten Fällen sogar schneller sein kann als eine Datenbank weil es sowieso nicht so viele Datensätze sind. usw. Da gibt enlose Möglichkeiten. Seit ich aber EntityFramework kenne verwende ich fast nichts anderes mehr.

    Johannes schrieb:

    Es ist nicht so, dass ich nichts lernen will, aber Bergsteigen fängt man ja auch nicht am Mount Everest an.

    Gebe ich dir vollkommen recht. Immer kleine Schritte, so hat man auch immer wieder sein Erfolgserlebnis und wagt sich ans nächste, aber früher oder später will ich den Everest dann aber doch auch bezwingen oder?

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

    Vielen Dank!
    Ich hatte mir vor wenigen Wochen dein Tutorial 2.1.4.5 angesehen, doch konnte ich damals noch nicht alles sofort verinnerlichen.
    nur mal so:

    XML-Quellcode

    1. <Run Text="{Binding Brand}"/>
    nach dem "Run" wäre ich vermutlich sehr lange rumgerannt ^^

    Und Heureka! Ich hab's jetzt verstanden - "Du schummelst" - meine Frage von ganz oben hast du nicht beantwortet, du machst es anders und sicher sehr viel intelligenter!
    Ich hatte in meinem UserControl ein Binding auf die Variable "rs" aus dem Fenster und brauchte so natürlich den Parameter, um das jeweilige Feld anzusprechen.
    Das setzt natürlich voraus, dass in jedem Fenster unbedingt eine rs-Variable existieren muss. - Also nicht sehr flexibel! -
    Bei deiner Version gehört eine Public Property zum UserControl aus dem sich die internen Objekte ihre Daten holen und in der Anwendungsentwicklung kann man dann ein vollständiges Binding ohne irgendwelche Parameter schreiben.
    Ich hatte das Binding bereits fest programmiert und wollte es mit einem Parameter von außen anpassen, du bringst das Bindingobjekt nach draußen und kannst das Binding später in der Anwendungsentwicklung viel flexibler festlegen.

    War das verständlich? Ich denke jedenfalls, dass ich verstanden habe, wo mein Fehler lag.
    Wäre natürlich interessant, ob es für meinen Ansatz auch eine xaml-Lösung gegeben hätte.

    Für jetzt habe ich erst einmal genug "Brot" um mir die nächsten Nächte um die Ohren zu schlagen :/
    liebe Grüße und Vielen Dank
    aus dem nicht mehr so sehr verschneiten Erzgebirge
    Hallo

    Johannes schrieb:

    Bei deiner Version gehört eine Public Property zum UserControl

    Nicht ganz. du musst unterscheiden zwischen einem "normalen" Property und einem DependecyProperty. Das ist ein großer Unterschied. Auf ein normales Property kannst du nicht direkt binden, auf ein DependencyProperty schon.
    Ist aber nur einer von vielen Unterschieden, aber auch hierfür habe ich ein Kapitel wo ich das durchgehe.

    Johannes schrieb:

    Wäre natürlich interessant, ob es für meinen Ansatz auch eine xaml-Lösung gegeben hätte.

    Kurz gesagt - das ist die XAML Lösung. Nur weil CodeBehind im UserControl ist (Das DependencyProperty) bedeutet das nicht das dies nicht "die XAML Lösung" ist.
    Man muss hier unterscheiden. Schreibst du CodeBehind (so wie du) das einen Wert oder Daten in z.b. eine TextBox schreibt oder schreibst du CodeBehind in Form eines Dependency Properties welches dir dann damit Binding (über XAML) ermöglicht. Du erweiterst ja nur die Funktionalität eines Controls - in diesem Fall des Usercontrols.

    WPF ist für Binding konzipiert, es gibt trotzdem die CodeBehind mit mehr oder weniger den möglichkeiten die wir aus WinForms kennen, das direkte Ansprechen von Controls wenn diese einen Name haben.
    Warum aber wenn man doch per Binding arbeiten soll. Ja, soll man. Es gibt aber Dinge die kann man beruigt in der CodeBehind machen - und zwar alles was rein die UI betrifft und Datenunabhängig ist.

    Ansonsten sollte die CodeBehind leer bleiben. In diesem Fall hat ein DependencyProperty jetzt nichts mit einer Geschäftslogik oder Daten zu tun, es erweitert die funktionalität eines Controls, betrifft also rein die UI.

    Ich hoffe das war verständlich, ansonsten Frag hald einfach nach.
    Die WPF macht irre viel spass wenn man es mal verstanden hat richtig anzuwenden, auf der anderen Seite kann sie schnell zur frustration führen wenn man gegen sie Arbeitet, das ist der Grund warum ich jedem immer empfehle die WPF so zu Verwenden wie dies vorgesehen wurde.

    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,

    nerve ich dich schon?
    Entschuldige!
    Ich habe versucht, dein "Uni-Tool" etwas anzupassen, schon um zu verstehen, was du da alles zusammengezaubert hast.

    Ja, sorry, ich will zunächst mal die DAO Bibliothek benutzen. Ich habe da eine replizierte Datenbank laufen und Microsoft hat für Replikation den Support eingestellt. Klar, Replikation kann Probleme bereiten, aber es kommt auf den Einsatzzweck an und mit einer Web-Datenbank katapultiere ich mich (und meine "Kunden") in Sachen Datenschutz in eine völlig andere Liga.

    EntityFramework - Sicher eine gute Idee, aber da habe ich dann noch eine Baustelle!

    Ich hatte bis eben ein Problem und wollte dich fragen, doch das hat sich gelöst.

    Kann man hier auch einen Eintrag löschen? ist mir gerade nicht gelungen.

    Danke für dein Mühen!
    Johannes

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

    Hallo

    Kein Problem. Muss man nicht löschen. Kann man ja stehen lassen.

    Falls du zu diesem Thema noch fragen hast dann gerne hier ansonsten am besten ein neues Thema aufmachen.

    Keine Angst, du nervst nicht, dafür ist ein Forum ja immerhin da oder.

    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,
    na da hab ich dann doch noch eine Frage:

    Ich würde gern in das UserControl eine Suchfunktion einbauen.
    Zunächst in das Grid eine 3. GridColumn und dort einen Button und diesen mit einer DependencyProperty Searchable vom Typ Visibility ein und ausblenden.

    Oder doch lieber in den jeweiligen DataTriger anpassen und dort den Button platzieren (habe ich dann viele unterschiedliche Button?).
    Mehrere Controls wollte der DataTrigger nicht, muss ich die in z.B. in
    ein eigenes Grid oder Panel zusammenfassen.
    Wenn der Button bei Searchable Collapsed ausgeblendet wird könnte die Textbox vergrößert werden.

    Nun möchte ich aber folgendes:
    Mit dem Button blende ich die TextBox aus und stattdessen eine ComboBox für eine Schnellsuche ein.
    Wenn in der Combobox ein Wert ausgewählt und mit Enter bestätigt wurde, dann wird wieder die Textbox eingeblendet und die Combobox verschwindet.

    Ich fürchte, dass das ist für dich wieder so eine simple Frage, nach dem Motto "WPF macht Spaß" und ich stochere noch etwas im Nebel.

    Danke!
    Johannes
    Hallo

    OK. Langsam.
    Da ist einiges an Wirrwar drinnen.

    Johannes schrieb:

    dort einen Button und diesen mit einer DependencyProperty Searchable vom Typ Visibility ein und ausblenden.

    What? Ein Property das bestimmt ob gesucht werden kann oder nicht und dann gibt es einen Button?
    Was hast du vor? Wenn der User suchen können soll (Searchable = true) dann soll doch eine TextBox vorhanden sein in welcher der User suchen können soll oder nicht? Was soll da ein Button?

    Johannes schrieb:

    Mit dem Button blende ich die TextBox aus und stattdessen eine ComboBox für eine Schnellsuche ein.

    Sehe ich das also richtig? Es soll zwei arten von Suche geben und der User soll entscheiden können ob er die Schnellsuche mittels ComboBox oder mittels TextBox (Volltextsuche) verwenden will. Richtig?

    Johannes schrieb:

    Wenn in der Combobox ein Wert ausgewählt und mit Enter bestätigt wurde, dann wird wieder die Textbox eingeblendet und die Combobox verschwindet.

    ???

    In Sachen Usability ist das alles ein komisches verhalten und klingt als hätte ich es nicht verstanden oder du siehst den Wald vor lauter Bäumen nicht. (Das passiert mir beim Proggen des öfteren 8o ).

    Ich denke du willst folgendes (Nur ein vorschlag):
    Du willst von außen steuern können ob man bei dem UserControl suchen können soll. Wenn JA. Dann soll der User wählen können zwischen Volltextsuche und schnellsuche per Combobox.

    Falls ich dich falsch verstanden haben dann versuchs bitte nochmals zu erklären. Bitte ohne Details, einfach von Usersicht was wie wo passieren soll.

    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 das kann schon sein,

    irgendwie sprechen wir oft nicht dieselbe Sprache :(

    Also in meiner bisherigen Anwendung habe ich das so gemacht. (Die folgenden Bilder stehen im Formular praktisch an selber Stelle.)

    So ist der normale Eingabemodus, ein Textfeld mit dem ich in die Datenbank schreibe.

    Nach dem Buttonklick "btnSearch" wird das Eingabefeld überlagert (in WPF besser Visibility.Collapsed) und stattdessen die Suchfunktion für dieses Feld eingeblendet.
    Auf diese Weise kann der Benutzer zu jedem Steuerelement die passende Suchfunktion auswählen.
    Wenn er also nach Vornamen sucht, dann klickt er die Lupe neben Vorname und wenn er nach "grünen Schuhen sucht, dann eben die Lupe neben Schuhen".

    Das wäre hier im Normalfall ein Combobox Editable=False, mit Editable=True müsste ich im Hintergrund Eingaben in die Datenbank machen, wenn der Anwender etwa im Geschlechtsfeld statt "männlich" "weiblich" "neutral" jetzt plätzlich "Klingone" eintragen möchte....

    Ich hoffe, das ist jetzt verständlicher.

    Ich könnte natürlich mit dem Button ein Suchformular öffnen, doch meine Variante war intuitiver.

    Liebe Grüße
    Johannes