Invoke

  • WPF

Es gibt 42 Antworten in diesem Thema. Der letzte Beitrag () ist von faxe1008.

    Hi,

    Ich beschäftige mich zur Zeit mit WPF. ich möchte eine Vorgangsdauer mit Hilfe einer progressbar anzeigen. Problem hierbei ist das während des Vorgangs Dateien verschoben werden, was logischerweise zur Folge hat das ich einen Deleganten verwenden möchte:

    VB.NET-Quellcode

    1. Private Delegate Sub d_newItem()
    2. Private Sub newItem()
    3. ProgressBar1.Value = ProgressBar1.Value + 1
    4. End Sub
    5. Sub Vorgang()
    6. ' hier mit Schleife den Copyvorgang
    7. Me.Invoke(New d_newItem(AddressOf newItem))
    8. End Sub


    Allerdings unterkringelt VS mir Invoke. Was wäre hier die WPF Alternative?

    8-) faxe1008 8-)
    Ich glaube, du benötigst hierfür ein Dispatcher-Objekt. Aber denke daran, dass WPF ganz anders als WinForms ist und Controls auch mit XAML gezeichnet werden und nicht auf die Form gezogen.

    Also statt Control.Invoke nutzt du Dispatcher.Invoke

    Edit:// Mano, zu lahm.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    faxe1008 schrieb:

    Was stimmt da an meinem ViewModel nicht?
    Das du keines hast.
    Ein ViewModel ist nur ein ViewModel, wenn es nicht auf die Controls zugreift, sondern alles über Properties nach außen bekannt macht und bei Änderungen PropertyChanged von INotifypropertyChanged auslöst. Die Controls kümmern sich dann selbst darum, was sie anzeigen. So funktioniert nunmal das MVVM-Prinzip.
    @Artentus:

    Langsam. Habe erst vor 2 Tagen mit WPF angefangen. :)

    Du meinst ich sollte eine Property erstellen, die die Value beinhaltet und diese dann an das Control binden? Wieso sollte diese Methode so viel besser sei n?

    Entschuldigung wenn es nerven sollte, aber ich befasse mich noh nicht allzu lange damit :/ .

    8-) faxe1008 8-)
    Genau, und nicht vergessen PropertyChanged auszulösen, wenn sich der Wert der Property geändert hat, damit sich die Controls auch updaten können.
    Der Sinn dahinter ist, dass du in deinem Code nicht mit den Controls in Berührung kommst. Du verarbeitest ganz normal deine Daten, aber das wars. Für die Darstellung sind ganz alleine die Controls zuständig, nicht der Codebehind.
    @Artentus:

    Habe das mal ausprobiert:

    VB.NET-Quellcode

    1. <ProgressBar Value="{Binding progressval}" Name="Progresser" HorizontalAlignment="Left" Margin="10,7,0,0" Grid.Row="5" VerticalAlignment="Top" Width="467" Height="15" ValueChanged="Progresser_ValueChanged"/>


    VB.NET-Quellcode

    1. Dim pro As Integer = 0
    2. Public Property progressval As Integer
    3. Get
    4. Return pro
    5. End Get
    6. Set(value As Integer)
    7. pro = value
    8. End Set
    9. End Property


    Passt das so mit dem Binding?
    Was genau meintest du mit NotifyPropertychanged Event? Die Property-Set MEthode wird doch ausgelöst wenn sich etwas ändert wozu brauch man dann noch ein seperates Ereignis?

    8-) faxe1008 8-)
    Nö passt es nicht. Du musst das INotifyPropertyChanged Interface implementieren und dann beim setzen der Eigenschaft muss das PropertyChanged Event aufgerufen werden.
    Wenn du kein Ereignis feuerst, so wird die GUI nicht merken, dass sich der Wert verändert hat.

    Außerdem wäre es gut wenn dich an ein paar Guidlines halten würdest. Dim pro As Integer. pro? Was soll das heißen. Und progressval -> ProgressValue oder einfach nur Progress.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.

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

    Dieses Ereignis wird benötigt, um ein Update des Bindings am UI durchzuführen. Ansonsten bekommt es davon nichts mit.
    „Was daraus gefolgert werden kann ist, dass jeder intelligentere User sein Geld lieber für Bier ausgibt, um einen schönen Rausch zu haben, und nicht dieses Ranzprodukt.“

    -Auszug aus einer Unterhaltung über das iPhone und dessen Vermarktung.
    So:?

    VB.NET-Quellcode

    1. Implements INotifyPropertyChanged
    2. Public Event PropertyChanged As PropertyChangedEventHandler _
    3. Implements INotifyPropertyChanged.PropertyChanged
    4. Private Sub NotifyPropertyChanged(ByVal info As String)
    5. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    6. End Sub
    7. Dim ProgressVal As Integer = 0
    8. Public Property ProgressValue As Integer
    9. Get
    10. Return ProgressVal
    11. End Get
    12. Set(value As Integer)
    13. If ProgressVal <> value Then
    14. ProgressVal = value
    15. NotifyPropertyChanged("ProgressValue")
    16. End If
    17. End Set
    18. End Property

    8-) faxe1008 8-)
    @thefiloe:
    Irgendwie funktioniert dieser Test nich so ganz:

    Der Teil vom Window der relevant ist:

    VB.NET-Quellcode

    1. Height="350" Width="648.674" Loaded="MainWindow_Loaded_1">


    Progressbar:

    VB.NET-Quellcode

    1. <ProgressBar Maximum="{Binding ProgressMaximum}" Value="{Binding ProgressValue}" Name="Progresser" HorizontalAlignment="Left" Margin="10,7,0,0" Grid.Row="5" VerticalAlignment="Top" Width="467" Height="15"/>


    Hier der Codebehind:

    VB.NET-Quellcode

    1. Dim processValue As Integer = 0
    2. Public Property ProgressValue As Integer
    3. Get
    4. Return processValue
    5. End Get
    6. Set(value As Integer)
    7. If processValue <> value Then
    8. processValue = value
    9. NotifyPropertyChanged("ProgressValue")
    10. End If
    11. End Set
    12. End Property
    13. Dim processMaximum As Integer = 0
    14. Public Property ProgressMaximum As Integer
    15. Get
    16. Return processMaximum
    17. End Get
    18. Set(value As Integer)
    19. If processMaximum <> value Then
    20. processMaximum = value
    21. NotifyPropertyChanged("ProgressMaximum")
    22. End If
    23. End Set
    24. End Property
    25. Private Sub MainWindow_Loaded_1(sender As Object, e As RoutedEventArgs)
    26. ProgressMaximum = 10
    27. ProgressValue = 3
    28. End Sub


    Es funktioniert leider nicht :huh:

    8-) faxe1008 8-)

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

    Hast du den richtigen Datacontext? Bindings debuggen kann etwas nervig sein. Es werden dir aber im Ausgabefenster Bindingfehler angezeigt.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    @Artentus:

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class PropertyClass
    3. Implements INotifyPropertyChanged
    4. Public Event PropertyChanged As PropertyChangedEventHandler _
    5. Implements INotifyPropertyChanged.PropertyChanged
    6. Private Sub NotifyPropertyChanged(ByVal info As String)
    7. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    8. End Sub
    9. Dim processValue As Integer = 0
    10. Public Property ProgressValue As Integer
    11. Get
    12. Return processValue
    13. End Get
    14. Set(value As Integer)
    15. If processValue <> value Then
    16. processValue = value
    17. NotifyPropertyChanged("ProgressValue")
    18. End If
    19. End Set
    20. End Property
    21. Dim processMaximum As Integer = 0
    22. Public Property ProgressMaximum As Integer
    23. Get
    24. Return processMaximum
    25. End Get
    26. Set(value As Integer)
    27. If processMaximum <> value Then
    28. processMaximum = value
    29. NotifyPropertyChanged("ProgressMaximum")
    30. End If
    31. End Set
    32. End Property
    33. End Class


    Wie binde ich das jetzt elegant per XAML ein? Reicht das hier:

    VB.NET-Quellcode

    1. DataContext="PropertyClass"

    Und dann einfach die Bindings sowie oben angegeben reinbauen?

    8-) faxe1008 8-)
    Das ist noch kein Singletone. Ich regle das immer so, dass ich dann eine Statisch Eigenschaft "Instance" habe, die das Objekt zurückgibt (das hab ich übrigens von @thefiloe:). Außerdem heißen bei mir die ViewModelle auch immer ...ViewModel.

    Dann bindest du es so ein:

    XML-Quellcode

    1. xmlns:local="clr-namespace:SomeNamespace"
    2. DataContext = "{x:Static local:SomeViewModel.Instance}"