Windows Phone 8.1 XAML StringFormat - c#

I am trying to display some text along with binded data, for example, I have the code:
<TextBlock Text="{Binding Shorthand}" Style="{ThemeResource ListViewItemTextBlockStyle}" />
I want to add some text before 'Shorthand', from what I have read this would be possible by using StringFormat as a property of the Binding, something along the lines of:
<TextBlock Text="{Binding Path=Shorthand, StringFormat={0} text I want to add}" Style="{ThemeResource ListViewItemTextBlockStyle}" />
However this doesn't seem to work, is this no longer the way to do things in 8.1?

StringFormat isn't supported on WinRT. However, you can easily replace it by creating a custom converter:
public class StringFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return string.Format(parameter as string, value);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return null;
}
}
Then declare it in your page resources:
<Page.Resources>
<local:StringFormatConverter x:Name="StringFormat"/>
</Page.Resources>
And use it in your bindings:
<TextBlock Text="{Binding Path=SomeText, Converter={StaticResource ResourceKey=StringFormat}, ConverterParameter='Hello {0}'}" />

Like #KooKiz pointed out StringFormat at the moment isn't supported, but you could accomplish the same effect just breaking out your lines into inline Runs without a converter like;
<TextBlock>
<Run Text="Hey I wanted to put this text in front of "/>
<Run Text="{Binding Path=Shorthand}"/>
<Run Text=" and I also wanted some text after it. Neato.."/>
</TextBlock>
Hope this helps, cheers.

I used this approach (Written by Microsoft): https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.data.ivalueconverter
It works great!

Related

ComboBox Text ValueConverter Lag - C# WPF XAML

I currently have a combobox in my WPF application, but it seems like there's some lag before the value is converted.
The value converter converts a UUID/GUID to a name, but what shows up on the combobox is first the UUID/GUID for a split second and then the name shows up.
Here's a boiled down version of my combobox:
<ComboBox x:Name="MyComboBox"
Text="{Binding Path=GUID, Converter={StaticResource GUIDToNameValueConverter}, Mode=OneWay}"
ItemTemplate="{StaticResource MyTemplate}"
Style="{StaticResource MyStyle}"
ItemsSource="{Binding Source={x:Static myNameSpace:MyItems}, Path=Items}"
SelectionChanged="MyChangedEventHandler">
</ComboBox>
Here's the general gist of my valueconverter:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string GUID = (string)value;
MyObject myObject = GetObjectById(GUID);
return myObject.name;
}
Essentially, I want to get rid of the split second display of the GUID before the actual name shows up. I'm unsure why the GUID event shows up since the converter takes care of converting that to a name.
Let me know if this is enough information to have this question answered, if not, please request more parts of my code!

Multilingual WPF Application: not working with combobox

I have created a multilingual WPF application using Andre's answer from here. I'm binding text like this
<TextBlock Text="{DynamicResource Create}"/>
and can switch from english to french at runtime - nice! However, this does not work with ItemsSource. For example, I have a ComboBox that should display all available languages:
<ComboBox ItemsSource="{Binding AllLanguages, Source={StaticResource Locator}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{DynamicResource LanguageId}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Set up like this, the combobox displays no text. If I set the textblock's text inside to Text={LanguageId}, I see the LanguageIds 'eng', 'fr' etc., so the binding works.
When using a converter:
<TextBlock Text="{Binding LanguageId, Converter={StaticResource DynamicResourceConverter}"/>
languages are displayed as "English" and "French". When I switch the language, however, the converter is not called again and the language names are not updated - so that is no real workaround.
I'd be very thankful for a tip on the cause and how to fix this.
I'll explain first why a few things are not working.
....
<DataTemplate>
<TextBlock Text="{DynamicResource LanguageId}"/>
</DataTemplate>
....
This is a short hand for Text="{DynamicResource ResourceKey='LanguageId'}" which is a static string literal and does not involve any binding.
It would be great if the following was available, but unfortunetly is NOT POSSIBLE because the target for the binding is not a DependancyProperty.
....
<DataTemplate>
<TextBlock Text="{DynamicResource ResourceKey={Binding LanguageId}}"/>
</DataTemplate>
....
You are close with your workaround. My suggestion would be to try the following:-
....
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource DynamicResourceConverter}">
<Binding Path="LanguageId"/>
<Binding Path="SomeOtherPropertyThatChangesWhenLanguageIsSwitched" Source="{StaticResource Locator}"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
....
You will need to expand the DynamicResourceConverter to now implement also IMultiValueConverter. In a MultiBinding scenario, if either bound expression changes then the converter is called again. You would write the Converter such that it only operates on values[0] of the supplied object array as the second value is not needed and only provided a trigger for the converter to be called again.
public class DynamicResourceConverter: IValueConverter, IMultiValueConverter
{
....
// original converter implementation for IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
....
}
// newly added converter implementation for IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
//call the original converter method with one value (assuming you've checked the array has at least one item!!
return Convert(values[0], targetType, parameter, culture)
}
....
}

WP8 - Binding a value with a float to String conversion

I have a couple of gauges in my app, and I can't figure out how to add a converter to the text binding. I read a couple of guides on msdn but I didn't manage to figure that out (I've been coding for WP8 for just a couple of weeks).
This is is a piece of the gauge:
<gauges:MarkerGaugeIndicator Value="0"
gauges:LinearGaugeRange.IndicatorOffset="35"
x:Name="GaugeBarValore"
IsAnimated="True">
<gauges:MarkerGaugeIndicator.MarkerTemplate>
<DataTemplate>
<Grid Width="73" Height="35" UseLayoutRounding="False" d:LayoutRounding="Auto" Margin="10,-2,0,0">
<TextBlock x:Name="GaugeBarPercent" Text="{Binding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="20"
FontWeight="Thin" Margin="6,4,32,4" Width="35"/>
<Grid.RenderTransform>
<CompositeTransform Rotation="90" TranslateX="49" TranslateY="12" />
</Grid.RenderTransform>
</Grid>
</DataTemplate>
</gauges:MarkerGaugeIndicator.MarkerTemplate>
</gauges:MarkerGaugeIndicator>
The binding itself works, but I can see a lot of decimal numbers while the value moves from a round value to another.
I want to add a converter like this method:
private String double2String(double valore)
{
return Convert.ToString(Math.Round(valore)) + "%";
}
I just don't know where to put this method and how to add this as a converter inside the binding.
Thank you for your help! :)
Sergio
Create a class to hold your Converter method that implements IValueConverter interface, Example class is bellow. You have to implement method Convert and ConvertBack.
public class DoubleToString : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Math.Round((double)value).ToString() + "%";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return double.Parse(value as string);
}
}
then add the namespace to your XAML page.
xmlns:convert="clr-namespace:Your_project_name"
Next add your converter as a Resource type i to your XAML page..
<phone:PhoneApplicationPage.Resources>
<convert:DoubleToString x:Key="DoubleConvert" />
</phone:PhoneApplicationPage.Resources>
The x:Key value is the name we are going to call in our binding statement.
Then perform the data binding. I have a simple slider and a textblock with sliders value bound to the textblocks Text property
<StackPanel>
<Slider Name="slider" Maximum="100" Minimum="0" />
<TextBlock Text="{Binding Value, ElementName=slider, Converter={StaticResource DoubleConvert}}" />
</StackPanel>
Define this converter as a resource in your parent view
<UserControl.Resources>
<local:double2String x:Key="convertDouble" />
</UserControl.Resources>
And add it to the binding
<TextBlock x:Name="GaugeBarPercent" Text="{Binding, Converter={StaticResource convertDouble}}"
Don't forget to import the namespace where the converter is defined to your view
xmlns:local="clr-namespace:YOUR_NAMESPACE"
The easier way is to use StringFormat. Like this:
<Label Text="{Binding Path=SomeProperty, StringFormat='{0:F2}%' }"/>

Use StringFormat to add a string to a WPF XAML binding

I have a WPF 4 application that contains a TextBlock which has a one-way binding to an integer value (in this case, a temperature in degrees Celsius). The XAML looks like this:
<TextBlock x:Name="textBlockTemperature">
<Run Text="{Binding CelsiusTemp, Mode=OneWay}"/></TextBlock>
This works fine for displaying the actual temperature value but I'd like to format this value so it includes °C instead of just the number (30°C instead of just 30). I've been reading about StringFormat and I've seen several generic examples like this:
// format the bound value as a currency
<TextBlock Text="{Binding Amount, StringFormat={}{0:C}}" />
and
// preface the bound value with a string and format it as a currency
<TextBlock Text="{Binding Amount, StringFormat=Amount: {0:C}}"/>
Unfortunately, none of the examples I've seen have appended a string to the bound value as I'm trying to do. I'm sure it's got to be something simple but I'm not having any luck finding it. Can anyone explain to me how to do that?
Your first example is effectively what you need:
<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Here's an alternative that works well for readability if you have the Binding in the middle of the string or multiple bindings:
<TextBlock>
<Run Text="Temperature is "/>
<Run Text="{Binding CelsiusTemp}"/>
<Run Text="°C"/>
</TextBlock>
<!-- displays: 0°C (32°F)-->
<TextBlock>
<Run Text="{Binding CelsiusTemp}"/>
<Run Text="°C"/>
<Run Text=" ("/>
<Run Text="{Binding Fahrenheit}"/>
<Run Text="°F)"/>
</TextBlock>
Please note that using StringFormat in Bindings only seems to work for "text" properties. Using this for Label.Content will not work
In xaml
<TextBlock Text="{Binding CelsiusTemp}" />
In ViewModel, this way setting the value also works:
public string CelsiusTemp
{
get { return string.Format("{0}°C", _CelsiusTemp); }
set
{
value = value.Replace("°C", "");
_CelsiusTemp = value;
}
}

WPF how to bind slider's value to label's content with StringConverter?

I have a simple slider and a plain label. Label's content is bound to slider's value and it works fine- when you move the slider , label's content changes e.g 23.3983928394 , 50.234234234 and so on
I'd like to round it to int values. 1,2,10....100 . But when I try to use a converter I get the "ivalueconverter does not support converting from a string".
How can I convert the slider's Value to an int in the converter?
Thank you
This is my XAML
<Grid.Resources>
<local:MyConvertor x:Key="stringconverter" />
</Grid.Resources>
<Slider x:Name="mySlider" Height="50" Width="276" Maximum="100"/>
<Label Content="{Binding ElementName=mySlider, Path=Value, Converter=stringconverter}" />
This is my stringconverter class
public class MyConvertor: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//How to convert string to int?
}
You could just use the StringFormat property here instead of creating a converter. The double value will be rounded to an int due to the # format specified.
<TextBlock Text="{Binding ElementName=mySlider, Path=Value, StringFormat={}{0:#}}"/>
If you want to keep the label, instead of using a TextBlock, you can use ContentStringFormat instead as Content takes in an object type.
<Label Content="{Binding ElementName=mySlider, Path=Value}" ContentStringFormat="{}{0:#}" />
To answer the question: the error is thrown because of
Converter=stringconverter
it has to be
Converter={StaticResource stringconverter}
In your converter you convert not string to int but double (Slider.Value) to object (Label.Content) which can be a string too. e.g.
return ((double)value).ToString("0");
or
return Math.Round((double)value);
you can use the Label's ContentStringFormat property
<Label Content="{Binding ElementName=Slider, Path=Value}"
ContentStringFormat="{}{0:N0}" />
Check the Slider's IsSnapToTickEnabled property

Categories

Resources