Laden...

Wpf - Textbox Binding 2 Variablen?

Erstellt von _Cashisclay vor 9 Jahren Letzter Beitrag vor 9 Jahren 5.227 Views
_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren
Wpf - Textbox Binding 2 Variablen?

Hallo Liebe Community,

ich brauche wieder mal eure Hilfe!

Ich hab folgendes Problem : Ich muss auf eine Textbox einen Wert Binden.

Nur muss gleichzeitig die Textbox TwoWay auf einen Slider gebunden sein.

So dass die Textbox wenn vorhanden einen Startwert bekommt (aus der Datenbank) und dieser automatisch auf den Slider gebunden wird. Sich aber auch ändert wenn er auf dem Slider geändert wird.

Hab aktuell schon paar Sachen ausprobiert aber komme nicht zu einem Erfolg, ich google jetzt weiter eventuell hat ja jemand von euch Erfahrung damit. Geht das überhaupt?

Grüße

2.223 Beiträge seit 2005
vor 9 Jahren

hallo _Cashisclay,

warum bindest Du die TextBox und den Slider nicht an ein einziges Property ?

Viele Grüße
Lars

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren

Hallo Lars Schmitt,

versuch ich auch schon die ganze zeit leider funktioniert das irgendwie nicht, ich muss dazu sagen mein Slider ist ein eigenes UserControl muss man beim Binden an Dependency Properties irgendwas beachten?

Grüße

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren

Ich komm nicht mal in meinen Converter, warum nur nicht? 😕


<local:RangeSlider x:Name="mySlider" VerticalAlignment="Center" Minimum="0" Maximum="86399" LowerValue="{Binding Von, Converter={StaticResource IntegerToHourConverter}}"/>
2.223 Beiträge seit 2005
vor 9 Jahren

hmm, eigentllich gibt es da nichts besonderes zu beachten

ich frage mich nur ob ein UserControl für ein Slider das richtige ist, aber das sollte hier egal sein

zeige doch mal ein wenig mehr von deinem Code, dann können wir Dir bestimmt besser helfen

Viele Grüße
Lars

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren

Mein RangeSlider :

<UserControl x:Class="RangeSlider"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Watchdog"
             mc:Ignorable="d" 
             d:DesignHeight="20" d:DesignWidth="300"     
             x:Name="root">

    <UserControl.Resources>
        
        <!-- Farbverlauf - Thumb -->
        
        <LinearGradientBrush x:Key="Thumb" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="#f7f7f7"/>
            <GradientStop Offset="1" Color="#bcbcbc"/>
        </LinearGradientBrush>

        <!-- Style - Thumb -->
        
        <Style x:Key="Thumb_Style" TargetType="{x:Type Thumb}">
            <Setter Property="SnapsToDevicePixels" Value="true"/>
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Setter Property="Height" Value="14"/>
            <Setter Property="Width" Value="14"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Ellipse Name="Ellipse" Fill="{StaticResource Thumb}" Stroke="#404040" StrokeThickness="1" />
                        
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Ellipse" Property="Fill" Value="#808080"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter TargetName="Ellipse" Property="Fill" Value="#EEEEEE"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                        
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!-- ControlTemplate - Slider -->
        
        <ControlTemplate x:Key="RangeSlider" TargetType="{x:Type Slider}">
            <Border SnapsToDevicePixels="true" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <Rectangle x:Name="PART_SelectionRange"/>

                    <Track x:Name="PART_Track" Grid.Row="1">
                        <Track.Thumb>
                            <Thumb x:Name="Thumb" Style="{StaticResource Thumb_Style}"/>
                        </Track.Thumb>
                    </Track>
                </Grid>
            </Border>
        </ControlTemplate>

    </UserControl.Resources>
    
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="10"/>
        </Grid.ColumnDefinitions>
        
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>

        <Grid Grid.Column="1">
            <Border BorderThickness="2,0,2,0" BorderBrush="DarkGray" Margin="-2,0,-2,0"/>

            <Border BorderThickness="0,2,0,0" BorderBrush="DarkGray" VerticalAlignment="Center" Height="1" Margin="5,0,5,0"/>

            <Slider x:Name="LowerSlider" Minimum="{Binding ElementName=root, Path=Minimum}" Maximum="{Binding ElementName=root, Path=Maximum}" Value="{Binding ElementName=root, Path=LowerValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Template="{StaticResource RangeSlider}"  Margin="0,0,10,0" ToolTip="Von" VerticalAlignment="Center"/>

            <Slider x:Name="UpperSlider" Minimum="{Binding ElementName=root, Path=Minimum}" Maximum="{Binding ElementName=root, Path=Maximum}" Value="{Binding ElementName=root, Path=UpperValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Template="{StaticResource RangeSlider}"  Margin="10,0,0,0" ToolTip="Bis" VerticalAlignment="Center"/>
        </Grid>
    </Grid>
    
</UserControl>

Partial Public Class RangeSlider
    Inherits UserControl
    Implements ComponentModel.INotifyPropertyChanged

    Public Sub New()

        ' Dieser Aufruf ist für den Designer erforderlich.
        InitializeComponent()

        ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.

        Me.DataContext = Me
    End Sub

    Public Shared ReadOnly MinimumProperty As DependencyProperty = DependencyProperty.Register("Minimum", GetType(Double), GetType(RangeSlider), New UIPropertyMetadata(0.0))
    Public Shared ReadOnly LowerValueProperty As DependencyProperty = DependencyProperty.Register("LowerValue", GetType(Double), GetType(RangeSlider), New UIPropertyMetadata(0.0))
    Public Shared ReadOnly UpperValueProperty As DependencyProperty = DependencyProperty.Register("UpperValue", GetType(Double), GetType(RangeSlider), New UIPropertyMetadata(0.0))
    Public Shared ReadOnly MaximumProperty As DependencyProperty = DependencyProperty.Register("Maximum", GetType(Double), GetType(RangeSlider), New UIPropertyMetadata(1.0))

    Public Shared ReadOnly IntervallProperty As DependencyProperty = DependencyProperty.Register("Intervall", GetType(Integer), GetType(RangeSlider), New UIPropertyMetadata())

    Public Property Minimum As Double
        Get
            Return CDbl(GetValue(MinimumProperty))
        End Get
        Set(value As Double)
            SetValue(MinimumProperty, value)
        End Set
    End Property
    Public Property LowerValue As Double
        Get
            Return CDbl(GetValue(LowerValueProperty))
        End Get
        Set(value As Double)
            SetValue(LowerValueProperty, value)
            Propertychange("LowerValue")
        End Set
    End Property
    Public Property UpperValue As Double
        Get
            Return CDbl(GetValue(UpperValueProperty))
        End Get
        Set(value As Double)
            SetValue(UpperValueProperty, value)
        End Set
    End Property
    Public Property Maximum As Double
        Get
            Return CDbl(GetValue(MaximumProperty))
        End Get
        Set(value As Double)
            SetValue(MaximumProperty, value)
        End Set
    End Property
    Public Property Intervall As Integer
        Get
            Return Convert.ToInt32(GetValue(IntervallProperty))
        End Get
        Set(value As Integer)

        End Set
    End Property


    Private Sub LowerSlider_ValueChanged(sender As System.Object, e As System.Windows.RoutedPropertyChangedEventArgs(Of System.Double)) Handles LowerSlider.ValueChanged
        UpperSlider.Value = Math.Max(UpperSlider.Value, LowerSlider.Value)

    End Sub

    Private Sub UpperSlider_ValueChanged(sender As System.Object, e As System.Windows.RoutedPropertyChangedEventArgs(Of System.Double)) Handles UpperSlider.ValueChanged
        LowerSlider.Value = Math.Min(UpperSlider.Value, LowerSlider.Value)

    End Sub

    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Private Sub Propertychange(ByVal Name As String)
        RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(Name))
    End Sub
End Class
L
155 Beiträge seit 2012
vor 9 Jahren

Das es im Slider-Control nicht funktioniert kann eventuell an folgenden liegen:

1.) Gib nicht deinem USerControl, den Namen root, dondern deinem 1. Element (i.d. Fall deinem Grid)

Das Problem ist nämlich sonst, dass der DatenContext deines UserControls überschrieben wird, wenn du es ein Parent bekommt (z.b. wenn du es einem WIndow hinzufügst)

2.) Du kannst das Binding auf den ElementNamen sparen. Gib nur den Path an. Da das Framework automatisch in den DatenContext schaut ob irgendwo die Property liegt (erst im Slider-DatenContext, dann im Grid usw. und im Grid würde es dann gefunden werden)

3.) Die TwoWay-Angabe kannst du auch sparen, das ist bei Default und den UpdateTrigger auf PropertyChanged kannst du auch sparen, weil du im Hintergrund an DependencyProperties bindest und nicht an INotifyPropertyChanged-Properties. Das es geubdated wird, lauft automatisch vom Framework über die Dependency-Properties ab. Damit ist der XAML-Code bereinigt.

4.) Ob der VB Code stimmt usw. müssen mal die anderen schauen, mein VB ist 🙄

aufgeräumter xaml-code in etwa so:


<UserControl x:Class="WpfApplication1.SliderControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <UserControl.Resources>

        <!--  Farbverlauf - Thumb  -->

        <LinearGradientBrush x:Key="Thumb" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="#f7f7f7" />
            <GradientStop Offset="1" Color="#bcbcbc" />
        </LinearGradientBrush>

        <!--  Style - Thumb  -->

        <Style x:Key="Thumb_Style"
               TargetType="{x:Type Thumb}">
            <Setter Property="SnapsToDevicePixels" Value="true" />
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="Height" Value="14" />
            <Setter Property="Width" Value="14" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Ellipse Name="Ellipse"
                                 Fill="{StaticResource Thumb}"
                                 Stroke="#404040"
                                 StrokeThickness="1" />

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="Ellipse" Property="Fill" Value="#808080" />
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter TargetName="Ellipse" Property="Fill" Value="#EEEEEE" />
                            </Trigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!--  ControlTemplate - Slider  -->

        <ControlTemplate x:Key="RangeSlider"
                         TargetType="{x:Type Slider}">
            <Border BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    SnapsToDevicePixels="true">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto"
                                       MinHeight="{TemplateBinding MinHeight}" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>

                    <Rectangle x:Name="PART_SelectionRange" />


                    <Track x:Name="PART_Track"
                           Grid.Row="1">
                        <Track.Thumb>
                            <Thumb x:Name="Thumb"
                                   Style="{StaticResource Thumb_Style}" />
                        </Track.Thumb>
                    </Track>
                </Grid>
            </Border>
        </ControlTemplate>

    </UserControl.Resources>

    <Grid x:Name="root">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Slider x:Name="LowerSlider"
                Grid.Row="0"
                Maximum="{Binding Path=Maximum}"
                Minimum="{Binding Path=Minimum}"
                Template="{StaticResource RangeSlider}"
                Value="{Binding Path=LowerValue}" />


        <Slider x:Name="UpperSlider"
                Grid.Row="1"
                Maximum="{Binding Path=Maximum}"
                Minimum="{Binding Path=Minimum}"
                Template="{StaticResource RangeSlider}"
                Value="{Binding Path=UpperValue}" />
    </Grid>

</UserControl>

in c#


public partial class SliderControl : UserControl
    {
        public SliderControl()
        {
            InitializeComponent();

            root.DataContext = this;
        }

        #region Maximum

        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(SliderControl), new PropertyMetadata(10.0));

        #endregion

        #region Minimum

        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(double), typeof(SliderControl), new PropertyMetadata(1.0));

        #endregion

        #region LowerValue

        public double LowerValue
        {
            get { return (double)GetValue(LowerValueProperty); }
            set { SetValue(LowerValueProperty, value); }
        }

        public static readonly DependencyProperty LowerValueProperty =
            DependencyProperty.Register("LowerValue", typeof(double), typeof(SliderControl), new PropertyMetadata(2.0));

        #endregion

        #region UpperValue

        public double UpperValue
        {
            get { return (double)GetValue(UpperValueProperty); }
            set { SetValue(UpperValueProperty, value); }
        }

        public static readonly DependencyProperty UpperValueProperty =
            DependencyProperty.Register("UpperValue", typeof(double), typeof(SliderControl), new PropertyMetadata(2.0));

        #endregion

    }

Im Aufrufer Xaml


 <this:SliderControl VerticalAlignment="Top" Height="100" x:Name="test"/>
        
        <TextBox VerticalAlignment="Center" Text="{Binding ElementName=test,Path=LowerValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>

        <TextBox VerticalAlignment="Bottom" Text="{Binding ElementName=test,Path=UpperValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>

Statt direkt die Textbox dann das Control zu binden, könntest du auch eine Property aus dem ViewModel oder ein DP aus dem CodeBehind nutzen, funktioniert aber auf jeden Fall so!

Mit freundlichen Grüßen
lutzeslife

5.657 Beiträge seit 2006
vor 9 Jahren

Hi _Cashisclay,

ganz allgemein gesagt, sollte man bei Problemen mit DataBindings immer erstmal ins Ausgabefenster schauen. Dort wird zur Laufzeit eine Fehlermeldung ausgegeben, wenn ein Pfad zu einer Eigenschaft nicht gefunden wird. Um Probleme weiter einzugrenzen, empfehle ich auch den DebugConverter.

Christian

Weeks of programming can save you hours of planning

2.223 Beiträge seit 2005
vor 9 Jahren

hallo lutzeslife,

Das es im Slider-Control nicht funktioniert kann eventuell an folgenden liegen:

1.) Gib nicht deinem USerControl, den Namen root, dondern deinem 1. Element (i.d. Fall deinem Grid)

Das Problem ist nämlich sonst, dass der DatenContext deines UserControls überschrieben wird, wenn du es ein Parent bekommt (z.b. wenn du es einem WIndow hinzufügst)

2.) Du kannst das Binding auf den ElementNamen sparen. Gib nur den Path an. Da das Framework automatisch in den DatenContext schaut ob irgendwo die Property liegt (erst im Slider-DatenContext, dann im Grid usw. und im Grid würde es dann gefunden werden)

hmm, ich glaube an dieser Stelle hast du ein kleinigkeit übersehen, denn an dieser Stelle wird nicht über den DataContext auf die jeweiligen Eigenschaften zugegriffen.

Viele Grüße
Lars

L
155 Beiträge seit 2012
vor 9 Jahren

Hallo Lars, was genau meinst du?

Mit freundlichen Grüßen
lutzeslife

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren

Bisher hat nichts geholfen ;/

L
155 Beiträge seit 2012
vor 9 Jahren

Was sagt das Ausgabe-Fenster? Binding Fehler können dadurch oft gefunden werden.

Mit freundlichen Grüßen
lutzeslife

5.299 Beiträge seit 2008
vor 9 Jahren

also iwie führt sich das Slider-Control selbst ad absurdum in dem Moment, wo es seinen DataContext auf sich selbst setzt.
Da kann man dann evtl. nicht mehr von auswärts daran binden, bzw. wenn mans doch tut, sind natürlich die selbst-Bindungen weg - also an dem Punkt geht das glaub nicht auf.

ach - vlt. irre ich mich auch, k.A.

kommt mir halt eigentümlich vor.

Der frühe Apfel fängt den Wurm.

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren

Das Ausgabe Fenster sagt folgendes :

Fehlermeldung:
System.Windows.Data Error: 40 : BindingExpression path error: 'Von' property not found on 'object' ''RangeSlider' (Name='mySlider')'. BindingExpression:Path=Von; DataItem='RangeSlider' (Name='mySlider'); target element is 'RangeSlider' (Name='mySlider'); target property is 'LowerValue' (type 'Double')

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren

Hat jemand noch eine Idee? Könnte es wirklich mit dem auf sich selbstzeigenden DataContext zu tun haben?

_
_Cashisclay Themenstarter:in
277 Beiträge seit 2014
vor 9 Jahren

Joooooooooooop, konnte seit langer Zeit mal wieder in Ruhe über das Projekt gucken, der Debug Tipp war gut, hab das ganze mal ausgelagert und in einem neuen Projekt aufgebaut um, einen ganz neuen Blick über die Sache zu bekommen, war einen Binding Fehler und Konvertierungsfehler, viel Drama um nichts, aber die Tipps haben mir für die Zukunft trotzdem geholfen, danke.

Kann geschlossen werden.

V
3 Beiträge seit 2015
vor 9 Jahren

Joooooooooooop, konnte seit langer Zeit mal wieder in Ruhe über das Projekt gucken, der Debug Tipp war gut, hab das ganze mal ausgelagert und in einem neuen Projekt aufgebaut um, einen ganz neuen Blick über die Sache zu bekommen, war einen Binding Fehler und Konvertierungsfehler, viel Drama um nichts, aber die Tipps haben mir für die Zukunft trotzdem geholfen, danke.

Kann geschlossen werden.

Das Problem ist nämlich sonst, dass der DatenContext deines UserControls überschrieben wird, wenn du es ein Parent bekommt.

Hinweis von Coffeebean vor 9 Jahren

Werbung entfernt. Community-Regeln