WPF Binding with invalid value for source - wpf

I have a TextBox that binds to an integer property.
What can I do so that when there is nothing no valid text in the TextBox that the property gets set to 0.
Really I think this can be extended so that if the binding fails then we set the source to default(T).
I need a nudge in the right direction.
TargetNullValue is the opposite of what I'm looking for(I think), that sets the TextBox text when the source is null. I want when the TextBox text is an invalid binding value to set the source as its default.

Applying a Converter such as the following to your binding should do the trick:
public class TextConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
int actual = (int)value;
return actual.ToString();
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
string actual = (string)value;
int theValue = 0;
int.TryParse(actual, out theValue);
return theValue;
}
}
Your TextBox binding would look something like this:
<TextBox Text="{Binding ... Converter={StaticResource convert}}"></TextBox>
With the convertor defined as a resource of your Window/Control/...

Related

Binding 2 textboxes with calculated ratio

I have a model that contains a HorsePower and a Kilowatt property
1 HP = 0.745 KW
I then have 2 textboxes where i want to update 'the other' with the calculated value.
eg: if i input '100' into the bound HP textbox, i want the KW textbox to update with '74,5'
and vise versa : 74,5 into KW -> updates HP to 100
one solution i figured, would be to bind to only 1 property, eg: HP and then use a value converter for the KW textbox (and then update KW on property changed)
is there another way to do this ?
You will need a binding converter like this:
public class MinusValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
return 100 - System.Convert.ToInt32(value);
}
catch (Exception)
{
return null;
}
}//END Convert
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}//END ConvertBack
}//END class ValueToCurrentConverter : IValueConverter
And XAML:
<TextBox Name="tbHorsepower" Text="8"/>
<TextBox Text="{Binding ElementName=tbHorsepower, Path=Text, Converter={StaticResource SubstractFrom100}}" IsReadOnly="True">
<TextBox.Resources>
<local1:MinusValueConverter x:Key="SubstractFrom100"/>
</TextBox.Resources>
</TextBox>
(Your textboxes will most likely look different)

How to bind int to Visibility in WPF?

I have BudgetControlType Properties that has 1 .. 7 value
if(BudgetControlType ==1)
dataComboBox1.Visibility=Visibility.Visiblile;
dataComboBox2 to dataComboBox7 =Visibility.Hidden;
if(BudgetControlType ==2)
dataComboBox1.Visibility=Visibility.Visiblile;
dataComboBox2.Visibility=Visibility.Visiblile;
dataComboBox3 to dataComboBox7 =Visibility.Hidden;
and so on...
How to do this in xaml?
Here is another approach I have used in the past using WPFConverters.
<TabItem.Visibility>
<Binding Path="SomeObservableCollection.Count">
<Binding.Converter>
<converters:ConverterGroup>
<converters:ExpressionConverter Expression="{}{0} > 0" />
<BooleanToVisibilityConverter />
</converters:ConverterGroup>
</Binding.Converter>
</Binding>
</TabItem.Visibility>
The ConvertGroup allows for multiple converters to be run sequentially.
The ExpressionConverter lets you define an arbitrary expression. In my case I want the TabItem to be visible if the collection count is greater than zero. Being defined in xaml means escaping characters and a somewhat awkward syntax but it works well enough!
The BooleanToVisibilityConverter converts the boolean result from the expression to our desired visibility.
For Elham, BudgetControlType could be bound to as long as it implemented INotifyPropertyChanged. An equals expression is done like this (I'm returning true if the bound value equals 7):
<converters:ExpressionConverter Expression="{}{0} == 7" />
You can use 1,2,4,8,... and convert it to Visibility
for example if your int number is 6 (2+4) then Control with paramerter 2 and Control with parameter 4 is Visible!
public class IntToVisibilityConverter:IValueConverter
{
private int val;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int intParam = (int)parameter;
val = (int)value;
return ((intParam & val) != 0) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
And in xaml :
<ComboBox Visibility="{Binding Path=MyEnum,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource IntToVisibilityConverter}, ConverterParameter=1}"/>
<ComboBox Visibility="{Binding Path=MyEnum,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource IntToVisibilityConverter}, ConverterParameter=2}"/>
<ComboBox Visibility="{Binding Path=MyEnum,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource IntToVisibilityConverter}, ConverterParameter=4}"/>
The best way I'd say would be to go with properties on your ViewModel, and bind to them.
example (you'll have to massage it a bit, but it's fairly simple from here) :
public Visibility dtcb1 { get; set; }
// all the rest till 7
// Somewhere in your logit / constructor :
dtcb1 = BudgetControlType == 1 ? Visible : Hidden;
// and so on
And on your xaml you'll bind your visibility to dtcb1
You can make the property boolean, and use a boolean to visibility converter as well (as per this answer for example, or just google yourself)

How to change formatting on specific cells in RadGridView

So I have a dynamic RadGridView. This means that I add Columns programmatically to the control. basically like this:
for (int i = 0; i < length; i++)
{
Binding b = new Binding(string.Format("Collection[{0}].ValueIWant", i));
binding.StringFormat = "{0:0.##}";
GridViewDataColumn column = new GridViewDataColumn()
{
Header = HeaderFor(i),
DataMemberBinding = b,
DataType = typeof(double?)
};
Control.columns.Add(column);
}
Now I need to add new lines that show the percentage between line 1 and 2, 2 and 3 and so on.
I've managed to do that but I'm not sure how I would manage to change the String.format specifically for those cells instead of the whole column.
CellTemplateSelector came to mind but I'm not sure that is a good idea as this might mean I have to set the binding again, not knowing the value of i and such. Also I only want to change the string.format on the binding.
As I'm manipulating the number as a double (0,5 is 50%, 50 is 5000%) I guess I have to mask the input as well. not sure if String.Format does that for me as well or if I should use RadMaskedInput
Use an IValueConverter to convert the column's value at each row to its appropriate representation. So for the binding on a computed column, use:
// bind to the row data itself, not any specific property
Binding b = new Binding();
b.Converter = new RowToFormattedValueConverter
This will send the complete row data to the converter; so you should be able to either use some existing property of the row to figure out which type it is (regular or percentage), or add an extra hidden property/column to specify it explicitly. The converter would then look something like this:
public class RowToFormattedValueConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var rowData = (MyModelType)value;
string formattedResult;
if (rowData.IsPerecentageRow)
{
formattedResult= string.Format("{0:P1}", rowData.ValueIWant);
}
else
{
formattedResult= string.Format("{0:0.##}", rowData.ValueIWant);
}
return formattedResult;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Silverlight: Sorting a column that's bound with an IValueConverter?

I have a silverlight datagrid and am dynamically adding the columns to it programmatically.
One of the columns is bound to a complex property which is a List of business objects.
In order to display the correct property on the right object in the list I'm using a custom value converter, passing in the List and the object's name as an optional parameter.
I'm then spinning through the list, and finding the correct object in the list to bind to its value property.
This works perfectly for display purposes, but it seems that it disables or messes up prohibits the sorting of the column.
I know it has to do specifically with the converter because any other dynamic column that I'm adding, with a standard property binding, it sorts fine.
Here is the code of my IValueConverter:
public class MetaDataValueConverter : IValueConverter
{
public MetaDataValueConverter()
{
}
public virtual object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string result = string.Empty;
List<XFerMetadata> md = (List<XFerMetadata>)value;
foreach(XFerMetadata val in md)
{
if (val.Name.Match(parameter.ToString()))
{
result = val.Value;
break;
}
}
return result;
}
public virtual object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
And here is the code where I'm dynamically creating the column and setting the binding.
DataGridTextColumn col = new DataGridTextColumn();
col.Header = schema.FieldName;
Binding binding = new Binding("MetaData");
binding.Converter = new MetaDataValueConverter();
binding.ConverterParameter = schema.FieldName;
col.Binding = binding;
cols.Add(col);

Silverlight 4 DataGrid edit null value's cell

I'm creating a DataGrid where I set ItemsSource of the grid to a WCF request result. I have some null values for some strings, and I want to be able to enter values for those null values. I have no problems editing/saving pre-populated non-null values, but I can't modify the values of cells which have been returned as null. How can I achieve this?
You can use a Converter in your Binding that converts the null value to an empty string. Here is some code for the converter:
public class NullToEmptyStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? string.Empty : value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == string.Empty ? null : value;
}
}

Resources