Cannot make converter work - c#

I am trying to learn how to use IValueConverter. I have the following converter:
[ValueConversion(typeof(string), typeof(string))]
public class RequiredFieldConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "";
return value.ToString() + "*";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "";
var str = value.ToString();
return str+"Convert Back testing";
}
}
I have added the RequiredFieldConverter resource in my app.xaml file and I want to try it as:
<TextBox Name="textBox2" Width="120" />
<TextBox Text="{Binding ElementName=textBox2, Path=Text, Converter=RequiredFieldConverter}" Name="textBox3" Width="120" />
I was hoping that when I type "hello" in textbox2 it shows "hello*" in textbox3 but it does not work. In fact I get the following exception at runtime:
{"Unable to cast object of type 'System.String' to type 'System.Windows.Data.IValueConverter'."}
also I know that the value converter function is working because it works when I do:
Content="{Binding Source={StaticResource Cliente}, Converter={StaticResource RequiredFieldConverter}}"

... You are getting the error as it trying to interpret RequiredFieldConverter as an reference to an IValueConverter. You need to use a StaticResource or DynamicResource to reference the converter as you have done in your second example.
<TextBox Text="{Binding ElementName=textBox2, Path=Text, Converter={StaticResouce RequiredFieldConverter}}" Name="textBox3" Width="120" />

Related

IValueConverter returning as object not value that is expected

I'm trying to convert a string on a label (or anything) to another string. This is for Icon fonts.
Converter
[ValueConversion(typeof(string), typeof(string))]
public class StringToIconConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string property = ((string)value).ToLower();
switch (property)
{
case "maximize": return #"\e901";
default return property;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
...
}
Then I've added it to my pages that need it
<Helpers:StringToIconConverter x:Key="Icon" />
And this is how I'm setting it
<Button Style="{StaticResource NavButton}"
Tag="Document"
Command="{Binding GotoDataMatrixEnterCommand}">
<Button.Content>
<Label Content="{Binding Source={RelativeSource Self},
Path=Tag,
Converter={StaticResource Icon},
UpdateSourceTrigger=LostFocus}"
Tag="Document" />
</Button.Content>
</Button>
And what I'm getting is
Windows.System.Control.Label in its place. Am I not converting it properly, I'm not quite sure why it is not replacing the correct information. I've tried a few things, and reading up online though I'm stuck at the moment. Plus when I try to debug it doesn't work (it never hits the breakpoints)
The problem is with the Binding on Label.Content. You should use RelativeSource, not Source.
It should be:
RelativeSource={RelativeSource Mode=Self}
Also, you have a syntactic error in the switch statement of StringToIconConverter: default return property; should be default: return property; (you're missing a colon).

How to pass Static Resource String to ConverterParameter in UWP

I m doing an UWP project and I wan't to format a string using a converter and Static resource String because the application is in mulitple languages.
Here is my converter :
public class StringFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null)
return null;
if (parameter == null)
return value;
return string.Format((string)parameter, value);
}
public object ConvertBack(object value, Type targetType, object parameter,
string language)
{
throw new NotImplementedException();
}
}
Here the string in my Resource Strings.Xaml file :
<x:String x:Key="nbItems">You have {0} items...</x:String>
Here the element where I wan't to pass this formatter :
<TextBlock Text="{x:Bind NbItems, Converter={StaticResource StringFormatConverter}, ConverterParameter={StaticResource nbItems}, Mode=OneWay}"/>
It's not working but if I do like this it works :
<TextBlock Text="{x:Bind NbItems, Converter={StaticResource StringFormatConverter}, ConverterParameter='You have {0} items..', Mode=OneWay}"/>
The parameters is always null in my converter, why it's not working ?
Not exactly certain why the parameter is null, however I have come up with a workaround. Move your strings into a Resource file (see here).
Then change the parameter you pass to your converter to the String Name, like so:
<TextBlock Text="{x:Bind NbItems, Converter={StaticResource StringFormatConverter}, ConverterParameter='FORMAT', Mode=OneWay}" />
Finally change your converter to load the the resource using the parameter like so:
public object Convert(object value, Type targetType, object parameter, string language) {
if (value == null)
return null;
var loader = new Windows.ApplicationModel.Resources.ResourceLoader();
var str = loader.GetString((string)parameter);
return string.Format(str, value);
}
Hope this helps.

Binding to last array element

So far, i have an ObservableCollection<T> for objects.
I always want to display the last inserted element into a TextBlock. I implemented two solutions in XAML, but both not working:
<TextBlock Text="{Binding Path=entries.Last().message, FallbackValue=...}" />
<TextBlock Text="{Binding Path=entries[entries.Length-1].message, FallbackValue=...}" />
This one works, but references the first entry:
<TextBlock Text="{Binding Path=entries[0].message, FallbackValue=...}" />
Am i missing something? Is it possible to do with pure XAML?
Solution 1 :
You can use a custom converter to achieve this :
Converter class :
class LastItemConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
IEnumerable<object> items = value as IEnumerable<object>;
if (items != null)
{
return items.LastOrDefault();
}
else return Binding.DoNothing;
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
Xaml :
<Application.Resources>
<local:LastItemConverter x:Key="LastItemConverter" />
</Application.Resources>
<TextBlock Text="{Binding Path=entries, Converter={StaticResource LastItemConverter}}" />
Solution 2 :
The other way is to create a new property in your model that returns the entry :
public Object LastEntry => entries.LastOrDefault();
Xaml :
<TextBlock Text="{Binding Path=LastEntry, ... " />

Converter Parameter In ItemTemplate

I have a collection of Checkboxes in a Listbox binding to an Enum which uses a converter. Code shown below:
<ListBox HorizontalAlignment="Left" Height="183" Margin="159,30,0,0" VerticalAlignment="Top" Width="144">
<ListBox.Resources>
<local:FlagsEnumValueConverter x:Key="FlagsConverter" />
</ListBox.Resources>
<CheckBox Content="Checkbox1" IsChecked="{
Binding Path=TestModel.TestEnum,
Converter={StaticResource FlagsConverter},
ConverterParameter={x:Static tc:TestEnum.Test1}}"/>
<CheckBox Content="Checkbox2" IsChecked="{
Binding Path=TestModel.TestEnum,
Converter={StaticResource FlagsConverter},
ConverterParameter={x:Static tc:TestEnum.Test2}}"/>
<CheckBox Content="Checkbox3" IsChecked="{
Binding Path=TestModel.TestEnum,
Converter={StaticResource FlagsConverter},
ConverterParameter={x:Static tc:TestEnum.Test3}}"/>
</ListBox>
Converter Code:
class FlagsEnumValueConverter : IValueConverter
{
private int mTargetValue;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var mask = (int)parameter;
mTargetValue = (int)value;
return ((mask & mTargetValue) != 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
mTargetValue ^= (int)parameter;
return Enum.Parse(targetType, mTargetValue.ToString());
}
}
I'd rather use an ItemTemplate to keep things clean and simple however I'm not sure what to do with the 'ConverterParameter' since it requires the specific Enum value. I've been Googling for a solution but haven't found one. I honestly don't even know where to start. Is this even possible?

How to pass a static value to IValueConverter in XAML

I would like to use static texts fetched from a web service in my WP7 app. Each text has a Name (the indetifier) and a Content property.
For example a text could look like this:
Name = "M43";
Content = "This is the text to be shown";
I would then like to pass the Name (i.e. the identifier) of the text to an IValueConverter, which would then look up the the Name and return the text.
I figured the converter to look something like this:
public class StaticTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
return App.StaticTexts.Items.SingleOrDefault(t => t.Name.Equals(value)).Content;
}
return null;
}
}
Then in the XAML:
<phone:PhoneApplicationPage.Resources>
<Helpers:StaticTextConverter x:Name="StaticTextConverter" />
</phone:PhoneApplicationPage.Resources>
...
<TextBlock Text="{Binding 'M43', Converter={StaticResource StaticTextConverter}}"/>
However, this does not seem to work and I am not sure that I pass in the value to the converter correctly.
Does anyone have some suggestions?
I finally found the answer. The answer was a mix between that of #Shawn Kendrot and another question I asked here: IValueConverter not getting invoked in some scenarios
To summarize the solution for using the IValueConverter I have to bind my control in the following manor:
<phone:PhoneApplicationPage.Resources>
<Helpers:StaticTextConverter x:Name="TextConverter" />
</phone:PhoneApplicationPage.Resources>
<TextBlock Text="{Binding Converter={StaticResource TextConverter}, ConverterParameter=M62}" />
Since the ID of the text is passed in with the converter parameter, the converter looks almost the same:
public class StaticTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter != null && parameter is string)
{
return App.StaticTexts.Items.SingleOrDefault(t => t.Name.Equals(parameter)).Content;
}
return null;
}
}
However, as it turns out, the binding and thus the converter is not invoked if it does not have a DataContext. To solve this, the DataContext property of the control just has to be set to something arbitrary:
<TextBlock DataContext="arbitrary"
Text="{Binding Converter={StaticResource TextConverter}, ConverterParameter=M62}" />
And then everything works as intended!
The problem lies in your binding. It will check the DataContext, and on this object, it will try to evaluate the properties M62 and ValueboxConsent on that object.
You might want to add static keys somewhere in your application where you can bind to:
<TextBlock Text="{Binding Source="{x:Static M62.ValueboxConsent}", Converter={StaticResource StaticTextConverter}}" />
Where M62 is a static class where your keys are located.. like so:
public static class M62
{
public static string ValueboxConsent
{
get { return "myValueBoxConsentKey"; }
}
}
If you want to use a value converter, you'll need to pass the string to the parameter of value converter
Xaml:
<TextBlock Text="{Binding Converter={StaticResource StaticTextConverter}, ConverterParameter=M43}"/>
Converter:
public class StaticTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter != null)
{
return App.StaticTexts.Items.SingleOrDefault(t => t.Name.Equals(parameter)).Content;
}
return null;
}
}
xmlns:prop="clr-namespace:MyProj.Properties;assembly=namespace:MyProj"
<TextBlock Text="{Binding Source={x:Static prop:Resources.MyString}, Converter={StaticResource StringToUpperCaseConverter}}" />

Categories

Resources