Based on this previously answered question, I'm trying to create an IMultiValueConverter
that will allow the Text property of a TextBox in WPF to be bound to the sum of several other TextBox values. I've mirrored the answer to the referenced question fairly strictly, yet when testing this I get an InvalidCastException
. In the code below, the lines commented out are the code from the aforementioned answer. I did try running this with the var
datatype instead of using double
(I dislike var
, just a preference), and received the
same error in the same place. I've tried changing the style of cast in various ways, including Convert.ToInt32
, (int)
, and even int.Parse
, but everything results in the same error, same location.
Does anybody have a clue as to what the problem with this could be? This is my first real foray into binding like this, so it could be I'm fundamentally misunderstanding it, but honestly don't think that's what it is...
public class AddListRecordsConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double result = 0.0;
try
{
double[] doubleValues = values.Cast<double>().ToArray();
foreach (var doubleValue in doubleValues)
{
result += doubleValue;
}
//var doubleValues = values.Cast<double>().ToArray();
//var leftPart = string.Join(" x ", doubleValues);
//var rightPart = doubleValues.Sum().ToString();
//var result = string.Format("{0} = {1}", leftPart, rightPart);
//return result;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Destination TextBox:
<TextBox x:Name="allRecords" Style="{StaticResource dataEntryTextBox}" Grid.Column="1" Grid.Row="6">
<TextBox.Text>
<MultiBinding Converter="{StaticResource AddListRecordsConverter}">
<Binding ElementName="allRecordsOne" Path="Text"></Binding>
<Binding ElementName="allRecordsTwo" Path="Text"></Binding>
</MultiBinding>
</TextBox.Text>
</TextBox>
Source TextBoxes:
<TextBox x:Name="allRecordsOne" Style="{StaticResource dataEntryTextBox}" Grid.Column="0" Grid.Row="4" GotFocus="SelectAllOnFocus_GotFocus" LostFocus="allRecords_LostFocus" />
<TextBox x:Name="allRecordsTwo" Style="{StaticResource readOnlyTextBox}" Grid.Column="0" Grid.Row="5" Text="{Binding ElementName=allRecordsOne, Path=Text}" GotFocus="SelectAllOnFocus_GotFocus" LostFocus="allRecords_LostFocus" />
<TextBox x:Name="allRecordsThree" Style="{StaticResource readOnlyTextBox}" Grid.Column="0" Grid.Row="6" Text="{Binding ElementName=allRecordsOne, Path=Text}" GotFocus="SelectAllOnFocus_GotFocus" LostFocus="allRecords_LostFocus" />
I simplified your example. Note that I used Mode="OneWay"
to avoid exception in ConvertBack method.
<StackPanel>
<TextBox x:Name="allRecords">
<TextBox.Text>
<MultiBinding Converter="{StaticResource AddListRecordsConverter}">
<Binding ElementName="allRecordsOne" Path="Text" Mode="OneWay"/>
<Binding ElementName="allRecordsTwo" Path="Text" Mode="OneWay"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
<TextBox x:Name="allRecordsOne" />
<TextBox x:Name="allRecordsTwo" />
</StackPanel>
the issue with the converter is that it receives two empty strings (default value of text) as input (values
) and can't handle them properly. it has to be more defensive
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double val = 0.0;
double result = 0.0;
foreach (var txt in values)
{
if (double.TryParse(txt.ToString(), out val))
result += val;
else
return "NaN";
}
return result.ToString();
}