How to do arithmetic with textboxes

RogerSchlueter-7899 1,256 Reputation points
2020-04-30T20:24:22.7+00:00

I have two textboxes on a wpf window that contain numeric values; call them txt1 and txt2. I want a third textbox (txt3) to show the difference between those two values.

I created a Property in code-behind called Diff defined as:

Diff = Cdec(txt1.Text) - Cdec(txt2.Text)

and bound that value as follows:

txt3.Text={Binding Path=Diff

However, at run-time the Property Diff is not found. How do I make that value available to be bound?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,710 questions
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,316 Reputation points
    2020-05-01T04:27:01.82+00:00

    Hi Roger, don't forget:

    • set DataContext or Source
    • Notify property changed
    • check input for invalid decimal numbers

    Try following simple demo.

    XAML:

    <Window x:Class="Window014"
            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"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window014" Height="450" Width="800" Loaded="Window_Loaded">
        <StackPanel>
        <TextBox x:Name="txt1" Margin="5" />
        <TextBox x:Name="txt2" Margin="5"/>
        <TextBox Text="{Binding Diff}" Margin="5"/>
      </StackPanel>
    </Window>
    

    CodeBehind:

    Imports System.ComponentModel
    Imports System.Runtime.CompilerServices
    
    Public Class Window014
      Implements INotifyPropertyChanged
    
      Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
        Me.DataContext = Me
      End Sub
    
      Private Sub txt_TextChanged(sender As Object, e As TextChangedEventArgs) Handles txt1.TextChanged, txt2.TextChanged
        Dim dec1 As Decimal = 0
        Decimal.TryParse(txt1.Text, dec1)
        Dim dec2 As Decimal = 0
        Decimal.TryParse(txt2.Text, dec2)
        Diff = dec1 - dec2
        OnPropChanged(NameOf(Diff))
      End Sub
    
      Public Property Diff As Decimal
    
      Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
      Private Sub OnPropChanged(<CallerMemberName> Optional propName As String = "")
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
      End Sub
    
    End Class
    

2 additional answers

Sort by: Most helpful
  1. Alex Li-MSFT 1,096 Reputation points
    2020-05-01T02:29:40.45+00:00

    Welcome to our Microsoft Q&A platform!

    I think you can use MultiBinding:

    Imports System.ComponentModel  
    Imports System.Globalization  
    Imports System.Runtime.CompilerServices  
      
    Class MainWindow  
        Implements INotifyPropertyChanged  
        Public Sub New()  
      
            ' This call is required by the designer.  
            InitializeComponent()  
      
            ' Add any initialization after the InitializeComponent() call.  
            Me.DataContext = Me  
      
      
        End Sub  
      
        Private _tb1 As String  
        Public Property tb1() As String  
            Get  
                Return _tb1  
            End Get  
            Set(value As String)  
                _tb1 = value  
                NotifyPropertyChanged("tb1")  
            End Set  
        End Property  
      
      
        Private _tb2 As String  
        Public Property tb2() As String  
            Get  
                Return _tb2  
            End Get  
            Set(value As String)  
                _tb2 = value  
                NotifyPropertyChanged("tb2")  
            End Set  
        End Property  
      
        Private _Diff As String  
      
        Public Property Diff() As String  
            Get  
                Return _Diff  
      
            End Get  
            Set(value As String)  
                _Diff = value  
                NotifyPropertyChanged("Diff")  
            End Set  
        End Property  
        Public Event PropertyChanged As PropertyChangedEventHandler _  
              Implements INotifyPropertyChanged.PropertyChanged  
      
        Private Sub NotifyPropertyChanged(ByVal info As String)  
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))  
        End Sub  
      
      
      
      
    End Class  
    Public Class MultiStringStateConverter  
        Implements IMultiValueConverter  
      
      
        Private Function IMultiValueConverter_Convert(value() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert  
      
            Return (System.Convert.ToInt32(value(0)) - System.Convert.ToInt32(value(1))).ToString()  
      
        End Function  
      
        Private Function IMultiValueConverter_ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack  
            Throw New NotImplementedException()  
        End Function  
    End Class  
      
    

    xaml:

      <Window.Resources>  
            <local:MultiStringStateConverter x:Key="MultiStringStateConverter"/>  
        </Window.Resources>  
        <StackPanel>  
            <TextBox Name="txt1" Text="{Binding tb1,UpdateSourceTrigger=PropertyChanged}"/>  
            <TextBox Name="txt2" Text="{Binding tb2,UpdateSourceTrigger=PropertyChanged}"/>  
            <TextBox Name="txt3">  
                <TextBox.Text>  
                    <MultiBinding UpdateSourceTrigger="PropertyChanged" Converter="{StaticResource MultiStringStateConverter}">  
                        <Binding Path="tb1"/>  
                        <Binding Path="tb2"/>  
                    </MultiBinding>  
                </TextBox.Text>  
            </TextBox>  
        </StackPanel>  
    

    7846-1.gif


  2. Alex Li-MSFT 1,096 Reputation points
    2020-05-05T01:18:36.273+00:00

    If you don't want set the DataContent to itself,you can use the following code:

    Imports System.ComponentModel
    Imports System.Globalization
    Imports System.Runtime.CompilerServices
    
    Class MainWindow
        Public Sub New()
            ' This call is required by the designer.
            InitializeComponent()
            ' Add any initialization after the InitializeComponent() call.
            Me.DataContext = New MyViewModel()
        End Sub
    End Class
    Public Class MyViewModel
        Implements INotifyPropertyChanged
    
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
        Private Sub NotifyPropertyChanged(ByVal info As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
        End Sub
        Private _tb1 As String = 0
        Public Property tb1() As String
            Get
                Return _tb1
            End Get
            Set(value As String)
                _tb1 = value
                NotifyPropertyChanged("tb1")
            End Set
        End Property
    
    
        Private _tb2 As String = 0
        Public Property tb2() As String
            Get
                Return _tb2
            End Get
            Set(value As String)
                _tb2 = value
                NotifyPropertyChanged("tb2")
            End Set
        End Property
    
        Private _Diff As String
    
        Public Property Diff() As String
            Get
                Return _Diff
    
            End Get
            Set(value As String)
                _Diff = value
                NotifyPropertyChanged("Diff")
            End Set
        End Property
    End Class
    Public Class MultiStringStateConverter
        Implements IMultiValueConverter
    
    
        Private Function IMultiValueConverter_Convert(value() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert
    
            Return (System.Convert.ToInt32(value(0)) - System.Convert.ToInt32(value(1))).ToString()
    
        End Function
    
        Private Function IMultiValueConverter_ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
            Throw New NotImplementedException()
        End Function
    End Class
    
    0 comments No comments