UserControl zur Übung (NUD)

  • WPF

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von asusdk.

    UserControl zur Übung (NUD)

    Hi @all,

    ich versuche mich gerade einfach zur Übung an einem eigenen NumericUpDown (aktuel nur für Integer).

    Mein Ansatz ist aktuel ist folgendes Xaml-Design :

    XML-Quellcode

    1. <UserControl x:Class="IntegerNudUCL"
    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:Delivery_Note_Creator"
    7. mc:Ignorable="d" d:DesignWidth="100" Height="26" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    8. <DockPanel LastChildFill="True">
    9. <Grid>
    10. <Grid.ColumnDefinitions>
    11. <ColumnDefinition Width="*"/>
    12. <ColumnDefinition Width="10"/>
    13. </Grid.ColumnDefinitions>
    14. <Grid.RowDefinitions>
    15. <RowDefinition Height="*"/>
    16. <RowDefinition Height="*"/>
    17. </Grid.RowDefinitions>
    18. <TextBox Name="ValueTextBox" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
    19. <Button Name="ValueUpButton" Margin="0,2,2,0" BorderThickness="0" FontSize="6" Content="∧" Grid.Row="0" Grid.ColumnSpan="1" Grid.Column="1" Click="ValueUpButton_Click"/>
    20. <Button Name="ValueDownButton" Margin="0,0,2,2" BorderThickness="0" FontSize="6" Content="∨" Grid.Row="1" Grid.ColumnSpan="1" Grid.Column="1"/>
    21. </Grid>
    22. </DockPanel>
    23. </UserControl>



    Um einen Wert mitzugeben, habe ich eine DependencyProperty im Codebehind des UserControls:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Property IntVal As Integer
    2. Get
    3. Return CInt(GetValue(IntValProperty))
    4. End Get
    5. Set(ByVal value As Integer)
    6. SetValue(IntValProperty, value)
    7. End Set
    8. End Property
    9. Public Shared ReadOnly IntValProperty As DependencyProperty =
    10. DependencyProperty.Register("IntVal",
    11. GetType(Integer), GetType(IntegerNudUCL),
    12. New PropertyMetadata(0))[/spoiler][spoiler]



    Doch fehlt mir nun der eigentliche "Funktionsansatz" wie ich nun weitermachen soll, unter anderem wird der von mir per DP gesetzte Wert zwar augenscheinlich gesetzt, der angezeigte Text hingegen nicht angepasst (bei einem neu erstellten Control.)

    XML-Quellcode

    1. <local:IntegerNudUCL IntVal="50"/>





    vollständiger aktueller CodeBehind:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Imports System.Runtime.CompilerServices
    3. Public Class IntegerNudUCL
    4. Inherits UserControl
    5. Public Property IntVal As Integer
    6. Get
    7. Return CInt(GetValue(IntValProperty))
    8. End Get
    9. Set(ByVal value As Integer)
    10. SetValue(IntValProperty, value)
    11. End Set
    12. End Property
    13. Public Shared ReadOnly IntValProperty As DependencyProperty =
    14. DependencyProperty.Register("IntVal",
    15. GetType(Integer), GetType(IntegerNudUCL),
    16. New PropertyMetadata(0))
    17. Public Sub New()
    18. InitializeComponent()
    19. ValueTextBox.Text = IntVal.ToString
    20. End Sub
    21. Public Sub ValueUP()
    22. IntVal += 1
    23. End Sub
    24. Private Sub ValueUpButton_Click(sender As Object, e As RoutedEventArgs)
    25. ValueUP()
    26. End Sub
    27. Private Sub ValueTextBox_TextChanged(sender As Object, e As TextChangedEventArgs) Handles ValueTextBox.TextChanged
    28. Dim TmpInteger As Integer = IntVal
    29. If Integer.TryParse(ValueTextBox.Text, TmpInteger) Then
    30. IntVal = TmpInteger
    31. End If
    32. End Sub
    33. End Class




    Evtl. kann mir jemand zumindest stichpunktartig sagen was ich nun zu tun/zu beachten habe um das Control entsprechend zum laufen zu kriegen.



    LG und Danke
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Und nimm bitte die Spoiler-Tags aus dem letzten Spoiler
    -- Done

    Jup debuggt hab ich, wenn ich den Button ValueUP verwende zählt er auch ab (den voreingestellten "50") hoch, nur direkt zu beginn zeigt er den MetaDaten-Wert an ( New PropertyMetadata(0) ) anstelle des eingestellten Wertes.

    des Weiteren, geht es mir insbesondere um die gute graue theorie, was ich bei einem eigenen WPF-UserControl zu beachten habe, evtl. sehe ich ja den Wlad vor lauter Bäumchen nicht ^^


    LG
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Ich sehe keine voreingestellten 50. Wo stellst du sie ein. Wäre es möglich, ob du am Anfang, wenn du die Form öffnest, das Property auf 50 setzt und keine IntValProperty brauchst sondern direkt einen Integer? Das könnte(muss nicht) die Lösung sein.
    Ich sehe keine voreingestellten 50


    die stelle ich in dem jeweiligen Fenster ein in welchem ich das UCL auch benutzen möchte (wie oben ersichtlich mit:)

    XML-Quellcode

    1. <local:IntegerNudUCL IntVal="50"/>


    LG
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    @asusdk

    Leider arbeitest du wieder nicht mit Binding, was dir wiedermal zum verhängnis wird. Nachfolgend ein Beispiel für das von dir versuchte nur mittels Binding.
    Du siehst, es ist viel weniger code, man weis sofort was es macht und es funktioniert.

    XML-Quellcode

    1. <UserControl x:Class="NumUpDown"
    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:WpfApp2"
    7. mc:Ignorable="d"
    8. d:DesignHeight="40.413" d:DesignWidth="83.495">
    9. <DockPanel LastChildFill="True">
    10. <Grid>
    11. <Grid.ColumnDefinitions>
    12. <ColumnDefinition Width="*"/>
    13. <ColumnDefinition Width="Auto"/>
    14. </Grid.ColumnDefinitions>
    15. <Grid.RowDefinitions>
    16. <RowDefinition Height="*"/>
    17. <RowDefinition Height="*"/>
    18. </Grid.RowDefinitions>
    19. <TextBox Name="ValueTextBox" Grid.RowSpan="2" Grid.ColumnSpan="1" VerticalContentAlignment="Center" HorizontalContentAlignment="Right"
    20. Text="{Binding IntVal, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
    21. <Button Name="ValueUpButton" BorderThickness="0" Content="∧" Grid.Row="0" Grid.ColumnSpan="1" Grid.Column="1"/>
    22. <Button Name="ValueDownButton" BorderThickness="0" Content="∨" Grid.Row="1" Grid.ColumnSpan="1" Grid.Column="1"/>
    23. </Grid>
    24. </DockPanel>
    25. </UserControl>


    Code:

    VB.NET-Quellcode

    1. Public Class NumUpDown
    2. Public Property IntVal As Integer
    3. Get
    4. Return GetValue(IntValProperty)
    5. End Get
    6. Set(ByVal value As Integer)
    7. SetValue(IntValProperty, value)
    8. End Set
    9. End Property
    10. Public Shared ReadOnly IntValProperty As DependencyProperty =
    11. DependencyProperty.Register("IntVal",
    12. GetType(Integer), GetType(NumUpDown),
    13. New PropertyMetadata(0))
    14. End Class


    Ja, mehr ist es nicht.
    Ein Tipp von mir: Um mittels den Buttons nun die Werte rauf oder runter zu schalten verwende doch bitte Commands welche auch als Dependency Properties implementiert sind.

    PS: Ideal wäre es natürlich wenn man sowas nicht als Usercontrol sondern als eigenes Control erstellt aber ich weis nicht ob du es überhaupt in anderen Projekten auch weiterverwenden 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. ##

    Hi @Nofear23m

    Ich arbeite zugegebenermaßen hier im UCL ohne Binding, da ich mich erstmal schritt für Schritt rantasten wollte, ich hatte in den ersten Varianten Binding mit drin, da es allerdings nicht den gewünschten erfolg erzielte (lag wohl daran das ich den DataContext auf RelativeSource Self gesetzt hatte ?), "versuchte" ich mich einfach durch ^^.
    Im Eigentlichen Programm (vormals ohne UCL sondern mit einer "normalen" Textbox) verwende ich vollständig Binding, nur eben nach wie vor ohne MVVM.

    Ich werde deine Version gleich mal testen, danke dir

    Du siehst, es ist viel weniger code, man weis sofort was es macht und es funktioniert.

    Ich muss auch zugeben das ich so nie draufgekommen wäre, da ich mit datenkontext noch so meine Verständnissprobleme habe.



    Nachtrag:
    Ein Tipp von mir: Um mittels den Buttons nun die Werte rauf oder runter zu schalten verwende doch bitte Commands welche auch als Dependency Properties implementiert sind.

    hm mal gucken ob ich commands als DP überhaupt hinkriege, bei Commands verwende ich nach wie vor deine RelayCommand-Klasse und kopier mir immer ein Command asl vorlage, mal gucken ob ichs entsprechend angepasst bekomme. p.S. da ich die funktion auch mit Scrollen erreichen möchte, weiss ich nicht inwieweit das als Command sinnvoll ist/wäre ?

    Ideal wäre es natürlich wenn man sowas nicht als Usercontrol sondern als eigenes Control erstellt aber ich weis nicht ob du es überhaupt in anderen Projekten auch weiterverwenden willst.

    theoretisch wäre es durchaus praktisch, müsst ich mal gucken was der Unterschied zwischen Control erstellen / Usercontrol erstellen ist





    Nachtrag2:
    @Nofear23m

    Ich verwende nun folgenden Xaml:
    Spoiler anzeigen

    XML-Quellcode

    1. <UserControl x:Class="IntegerNudUCL"
    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:Delivery_Note_Creator"
    7. mc:Ignorable="d" d:DesignWidth="100" Height="26">
    8. <DockPanel LastChildFill="True">
    9. <StackPanel Margin="-1,1,0,1" Orientation="Vertical" DockPanel.Dock="Right">
    10. <Button Margin="0,-1,0,0" Padding="0" Height="13" Width="9" Name="ValueUpButton" BorderThickness="0" FontSize="6" Content="∧" Grid.Row="0" Grid.ColumnSpan="1" Grid.Column="1" Click="ValueUpButton_Click" Background="#FFABADB3"/>
    11. <Button Margin="0,0,0,0" Padding="0" Height="13" Width="9" Name="ValueDownButton" BorderThickness="0" FontSize="6" Content="∨" Grid.Row="1" Grid.ColumnSpan="1" Grid.Column="1" Click="ValueDownButton_Click" Background="#FFABADB3"/>
    12. </StackPanel>
    13. <TextBox Name="ValueTextBox" Text="{Binding IntVal, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Grid.RowSpan="2" Grid.ColumnSpan="1" DockPanel.Dock="Left"/>
    14. </DockPanel>
    15. </UserControl>


    Und folgenden CodeBehind:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Imports System.Runtime.CompilerServices
    3. Public Class IntegerNudUCL
    4. Inherits UserControl
    5. Public Property IntVal As Integer
    6. Get
    7. Return CInt(GetValue(IntValProperty))
    8. End Get
    9. Set(ByVal value As Integer)
    10. SetValue(IntValProperty, value)
    11. End Set
    12. End Property
    13. Public Shared ReadOnly IntValProperty As DependencyProperty =
    14. DependencyProperty.Register("IntVal",
    15. GetType(Integer), GetType(IntegerNudUCL),
    16. New PropertyMetadata(0))
    17. Public Sub ValueUP()
    18. IntVal += 1
    19. End Sub
    20. Public Sub ValueDown()
    21. IntVal -= 1
    22. End Sub
    23. Private Sub ValueUpButton_Click(sender As Object, e As RoutedEventArgs)
    24. ValueUP()
    25. End Sub
    26. Private Sub ValueDownButton_Click(sender As Object, e As RoutedEventArgs)
    27. ValueDown()
    28. End Sub
    29. Private Sub ValueTextBox_MouseWheel(sender As Object, e As MouseWheelEventArgs) Handles ValueTextBox.MouseWheel
    30. If e.Delta > 0 Then
    31. ValueUP()
    32. Else
    33. ValueDown()
    34. End If
    35. End Sub
    36. End Class


    Habe aber nun ein gänzlich unerwartetes Problem. Wenn ich um den Wert zu erhöhen, die Sub ValueUP nutze in dem ich auf den ValueUpButton klicke, funktioniert alles so wie ich es erwarten würde, nutze ich stattdessen das hochscrollen, welches ja auf die selbe Sub ValueUP zugreift. Dann scheint das Binding nicht zu greifen bis ich erneut in das Control hineinklicke, so als würde der UpdateSourceTrigger obwohl dieser auf PropertyChanged steht dennoch auf lostfocus stehen ??

    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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