C# WPF add character to textbox without binding - c#

Can i simply add characters without binding this characters to my ViewModel?
I need these to show physical units like cm, mm, m, cm^3, ...
XAML:
<TextBox
Text="{Binding value_top}" //sth. like + "cm"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="50"/>
VW:
value_top = 22.9
Output aim:
22.9 cm
I know, I can overlay a Label, but i would like to know if there is another possibility.

Create a converter which will take the double and return a string. Here is an untested example to get you started:
public class DoubleToString: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var dbl = (double) value;
return $"{dbl} cm";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Double.Parse(Regex.Match(value.ToString(), "[\d.]+").Value);
}
}

Related

StringFormat freezes UI

I am making a ProgressBar with a TextBlock on top of it to notify the user about the download, I need the TextBlock to be bound to the value of the ProgressBar and formatted through XAML.
Like this:
<TextBlock x:Name="TxtBlock_Download" Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="3"
TextAlignment="Center"
Foreground="White" Padding="0,2,0,0">
<!--Updates the textbox by using multibinding-->
<TextBlock.Text>
<!--TODO fix the StringFormat -->
<MultiBinding Converter="{StaticResource ResourceKey=kk}" StringFormat="{}{}">
<Binding ElementName="ProgressBar_Download" Path="Value"/>
<Binding ElementName="ProgressBar_Download" Path="Maximum"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
I am also using a separate class to connect the two value and maximum
Like this:
class Binding : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values[0] + "/" + values[1].ToString();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return (value as string).Split('/');
}
}
But every time I try to format the string using StringFormat="" it freezes the UI until the download is complete (The download still works in the background but the program is frozen).
Since you can't format numbers that have already been converted to string I recommend you simply rewrite your converter (since you already have one) to take care of all the formatting you need:
class MyAwesomeProgressConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return ((double)values[0]).ToString("f2") + "/" + ((double)values[1]).ToString("f2");
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
Enumerable.Repeat(DependencyProperty.UnsetValue, targetTypes.Length).ToArray()
}
}
Also:
You don't need ConvertBack. Throw an Exception or return an Array of DependencyProperty.UnsetValue or Binding.DoNothing.
Don't name your Converter Binding - that might cause ambiguities

set cursor to hand on empty image-control

I have the following xaml:
<Border x:Name="brdImg3" BorderThickness="2" BorderBrush="Black" Margin="10,5,5,5" Cursor="Hand">
<Image x:Name="image3" Stretch="Fill" Cursor="Hand"/>
</Border>
The problem is, that the Hand-Cursor is only shown when the Source of Image is not null. When the Source is null, the Hand-Cursor is only shown when the Mouse is over the border. I need showing the Hand-Cursor when the Mouse is in the Border. How can I do this?
Use Converter in Cursor, check sources is null or empty. Logic is writen
Cursor={Binding Source,Converter={StaticResources CursorConverter}
public class CursorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!string.IsNullorEmpty(value.Tostring()))
{
return Cursor.Hand;
}
else
{
return Cursor.Arrow;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

C# ConvertBack from a binding column of textbox to a JObject

GoodDay!
I'm not good with wpf and binding, i need your help. I have already bind a Json Object (JObject) to a Column of TextBox.
<TextBox Width="250" Text="{Binding Path=Property, Converter={StaticResource jPropertyConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
I can show properly the data of the Jobject when i start my wpf window, now i need to ConvertBack the data modified when i modify one of the textbox of the columns, from that TextBox to the JObject, and the related JValue.
public class JPropertyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is JProperty)
{
JToken valoreProperty = (value as JProperty).Value;
if ((valoreProperty is JValue))
return (valoreProperty as JValue).Value;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
??
}
}
I can change the Value of the "leaves" of this JObject tree like:
(valoreProperty as JValue).Value = "Hello!";
How can i change the "leaves" of this JObject tree in the convert back?
Sorry for my english.
Thanks and bye
EDIT:
Thanks dbc! It works, many thanks!
Now i need to show in another column, every lenght of the value inside of the textbox, obviously if i change the value in the texbox the relative lenght value will change too.
I tried:
<DataGridTextColumn Header="Lunghezza2" IsReadOnly="True" Width="50" Binding="{Binding Path=Property.Value.Value.toString().Length, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
or in another way with a converter, passing a JProperty
public class LengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is JProperty)
{
JToken jValue = (value as JProperty).Value;
if ((jValue is JValue) && (jValue as JValue).Value != null)
return (jValue as JValue).Value.ToString().Length.ToString();
else
return "0";
}
else
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
But every try didn't works when i change the textbox value, any tips?
Many thanks again!
You don't need a converter for this purpose. Assuming your Property property returns a JProperty, you can bind directly to JProperty.Value.Value
<TextBox Name="PropertyTextBox"
Text="{Binding Path=Property.Value.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
If you want to disable the TextBox if the bound Property is not a "simple" JProperty (one with just a JValue for its value), you can do:
<TextBox Name="PropertyTextBox"
Text="{Binding Path=Property.Value.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Path=Property, Converter={StaticResource IsSimpleJPropertyConverter}, Mode=OneWay}"
/>
Using the converter
public class IsSimpleJPropertyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is JProperty)
{
JToken jValue = (value as JProperty).Value;
if (jValue is JValue)
return true;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

How to set the font case of a listbox item in WPF?

I have a ListBox in a WPF Window.
Based on the selected item of a ComboBox, the ListBox items are retrieved from database and bound as the ListBox's ItemSource.
I want to change the case of the ListBox items, i.e., when i bind all the items are in uppercase. I want to change the case to capitalize only the starting letter of a word.
You need a converter to achieve this behavior.
public class CaseConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
TextInfo textInfo = culture.TextInfo;
return textInfo.ToTitleCase(value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();;
}
}
Add this as resource
<Window.Resources>
<local:CaseConverter x:Key="MyCaseConverter"></local:CaseConverter>
</Window.Resources>
and use it in XAML as
<TextBlock Text="{Binding Name, Converter={StaticResource MyCaseConverter}}"/>

Converting Seconds to Minutes:Seconds

I am trying to bind a TextBlock's Text property by converting the Total Seconds i.e
1004 to Minutes:Seconds and I can successfully pull my Seconds from the XML but I dont know how to work with Getters and Setters so I can convert my Seconds to Minutes:Seconds
I had a look at TimeSpan and I know it can do what I ask but I dont know how to write the getter and setter so it will convert the integer values (seconds) to a Minute:Seconds format.
This is what I have in my Class so far
public class Stats
{
public TimeSpan Time {get;set;}
}
any help would be greatly appreciated,
thanks
John
To do it as a property you can do:
public class Stats {
public TimeSpan Time { get; set; }
public string TimeFormated { get { return Time.TotalMinutes + ":" + Time.Seconds; } }
}
Although you really should do that in your XAML since the what are doing is layout:
<StackPanel Orientation="Horizontal">
<TextBlock Text={Binding Time.TotalMinutes}" />
<TextBlock Text=":" />
<TextBlock Text=={Binding Time.Seconds}" />
</StackPanel>
Would recommend this converter instead (since the two previous answers will give you 2:1 when you really want 2:01 -
public class FriendlyTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
TimeSpan ts = TimeSpan.FromSeconds((int)value);
return String.Format("{0}:{1:D2}", ts.Minutes, ts.Seconds);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Note the :D2 specifier for format strings.
And to use it, you specify it at the same time as your binding:
<phone:PhoneApplicationPage.Resources>
<util:FriendlyTimeConverter x:Key="FriendlyTimeConverter"/>
</phone:PhoneApplicationPage.Resources>
...
<TextBlock Text="{Binding timeRemaining, Converter={StaticResource FriendlyTimeConverter}}" Name="TimerDisplay" Grid.Column="4" HorizontalAlignment="Right" Margin="12,0" Style="{StaticResource PhoneTextTitle2Style}"></TextBlock>
Use a converter.
XAML:
<phone:PhoneApplicationPage.Resources>
<classes:TimeSpanConverter x:Key="c" />
</phone:PhoneApplicationPage.Resources>
...
<TextBlock Text="{Binding Time, Converter={StaticResource c}}" />
C#:
public class TimeSpanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var time = (TimeSpan) value;
return time.TotalMinutes + ":" + time.Seconds;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}

Categories

Resources