I wanna bind my element height to another element height plus 20 pixel...
Is it possible to do such a thing?
<ScrollViewer Height="{Binding Height, ElementName=AnotherElement}">
Yes, by using a value converter
public class IncreaseByValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var passedInValue = System.Convert.ToDouble(value);
var increaseByValue = System.Convert.ToDouble(parameter);
return passedInValue + increaseByValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
defined as a static resource somewhere in your resources:
<local:IncreaseByValueConverter x:Key="IncreaseByValueConverter" />
used like this:
<ScrollViewer Height="{Binding Height, ElementName=AnotherElement, Converter={StaticResource IncreaseByValueConverter}", ConverterParameter="20">
You'll probably want to handle the converter parameter better by using some try/catch code in the IncreaseByValueConverter.Convert method. For example, make the parameter optional, so if it's not passed in, use a default value, or something like that...
Related
would it be possible to databind a static resource in Xamarin Forms?
Something like
Style="{StaticResource {Binding foo, StringFormat='SomeStyle{0}'}}"
Thanks
What you probably want is a Value Converter that handles locating the StaticResource for you. Full Microsoft Documentation here.
On your XAML element, you'd do something like this:
<Entry Style="{Binding foo, Converter={StaticResource FooToStyleConverter}}"/>
Your converter would work something like this:
public class FooToStyleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var someValue = (string)value; // Convert 'object' to whatever type you are expecting
// evaluate the converted value
if (someValue != null && someValue == "bar")
return (Style)App.Current.Resources["StyleOne"]; // return the desired style
return (Style)App.Current.Resources["StyleTwo"];
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Usually unused, but inverse the above logic if needed
throw new NotImplementedException();
}
}
Lastly, set up your converter as a Static Resource in App.xaml (or as a local resource on the page) so your page can properly reference it
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos">
<ContentPage.Resources>
<ResourceDictionary>
<local:FooToStyleConverter x:Key="FooToStyleConverter" />
....
UWP allows you to bind to a static method. I'm trying to get a time string by using
<TextBlock Text={x:Bind MyDateTime.ToString(MyPatternString)} />
where MyPatternString is "h:mm tt".
The problem is that DateTime's ToString() method has several different signatures. The first one receives an IFormatProvider. Because of this, I get a build error:
Function parameter 'provider' is invalid or missmatched
Is there any way to tell it that I wish to use the signature which accepts a string? I'd have thought it would automatically know this.
You can just add a method to your ViewModel and use that instead!
That way your binding expression can be changed to this:
<TextBlock Text={x:Bind FormatDateToString(MyDateTime)} />
Be advised that this works with the Windows 10 Anniversary Update only! More info on this matter here!
Found your question after searching for the answer myself; didn't find much help posted anywhere but did figure it out after some trial and error.
Function parameter 'provider' is invalid or mismatched
The reason for this that in XAML, a specific overload is being called which is DateTimeProperty.ToString(string, IFormatProvider).
In my case, any value I display is within a User Control so for each I added a CultureInfo dependency property and bound it to common source on my view model.
If C#, add:
using System.Globalization;
Then
public static readonly DependencyProperty CultureInfoProperty = DependencyProperty.Register(
"CultureInfo", typeof(CultureInfo), typeof(XyzReadoutView), new PropertyMetadata(default(CultureInfo)));
public CultureInfo CultureInfo
{
get { return (CultureInfo) GetValue(CultureInfoProperty); }
set { SetValue(CultureInfoProperty, value); }
}
This creates a local instance required for x:Bind, compile errors occur if using a static property.
And XAML:
<TextBlock Text={x:Bind MyDateTime.ToString('h:mm tt', CultureInfo)} />
Notice the format is surrounded with ' and not ".
Also, this will only update once as the mode for x:Bind has a default of Mode=OneTime; if you want changes on the DateTime or CultureInfo to propagate, the mode must be changed to Mode=OneWay.
<TextBlock Text={x:Bind MyDateTime.ToString('h:mm tt', CultureInfo), Mode=OneWay} />
If the format is user changeable, I would create a dependency property for it as well for updates and easy control binding back to a view model but that's just my personal preference.
public static readonly DependencyProperty DateTimeFormatProperty = DependencyProperty.Register(
"DateTimeFormat", typeof(string), typeof(XyzReadoutView), new PropertyMetadata(default(string)));
public string DateTimeFormat
{
get { return (string) GetValue(DateTimeFormatProperty); }
set { SetValue(DateTimeFormatProperty, value); }
}
And XAML:
<TextBlock Text={x:Bind MyDateTime.ToString(DateTimeFormat, CultureInfo), Mode=OneWay} />
You need to use an IValueConverter to format the text for display. Create a class which inherits from IValueConverter.
public class DateFormatter : IValueConverter
{
// This converts the DateTime object to the string to display.
public object Convert(object value, Type targetType,
object parameter, string language)
{
// Retrieve the format string and use it to format the value.
string formatString = parameter as string;
if (!string.IsNullOrEmpty(formatString))
{
return string.Format(
new CultureInfo(language), formatString, value);
}
// If the format string is null or empty, simply call ToString()
// on the value.
return value.ToString();
}
// No need to implement converting back on a one-way binding
public object ConvertBack(object value, Type targetType,
object parameter, string language)
{
throw new NotImplementedException();
}
}
Register it as resource on the Page and then you can specify the converter in the binding
<TextBlock Text={x:Bind MyDateTime, Converter={StaticResource DateFormatConverter}}, ConverterParameter="mm/dd/yyyy"}"/>
https://learn.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Data.IValueConverter
I am trying to format my string to have commas every 3 places, and a decimal if it is not a whole number. I have checked roughly 20 examples, and this is the closest I have come:
<TextBlock x:Name="countTextBlock" Text="{Binding Count, StringFormat={0:n}}" />
But I get a The property 'StringFormat' was not found in type 'Binding'. error.
Any ideas what is wrong here? Windows Phone 8.1 appears to differ from WPF, because all of the WPF resources say that this is how it is done.
(The string is updated constantly, so I need the code to be in the XAML. I also need it to remain binded. Unless of course I cannot have my cake and eat it too.)
It seems that, similar to Binding in WinRT, Binding in Windows Phone Universal Apps doesn't have StringFormat property. One possible way to work around this limitation is using Converter as explained in this blog post,
To summarize the post, you can create an IValueConverter implmentation that accept string format as parameter :
public sealed 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();
}
}
Create a resource of above converter in your XAML, then you can use it like this for example :
<TextBlock x:Name="countTextBlock"
Text="{Binding Count,
Converter={StaticResource StringFormatConverter},
ConverterParameter='{}{0:n}'}" />
I got the following code:
namespace SomeApp
{
public partial class MyClass : PhoneApplicationPage, IValueConverter
{
SOME METHODS...
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return true;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return true;
}
}
}
I would like to bind this class to a ValueConverter of a RadioButton. Is there any way to reference to the current class I'm working with? For example:
<phone:PhoneApplicationPage
x:Class="SomeApp.MyClass"
xmlns:local="clr-namespace:SomeApp">
<phone:PhoneApplicationPage.Resources>
<local:MyClass x:Key="myClass"/>
</phone:PhoneApplicationPage.Resources>
<RadioButton IsChecked="{Binding Converter={StaticResource myClass}}"/>
Thanks in advance =)
First using your page as a converter don't seem like a good idea, it's better practice to separate the converter fonctionality in a separate class. Particularly it would be a very bad idea to create a StaticResources of a converter created that way as it will use a lot of unessessary memory to create the whole page.
The only thing a converter can be binded in xaml is a StaticResource so you will not be able to do it in xaml but if you really want to do it you could do it by creating the binding from code behind (for example in the constructor of the page):
Binding binding=new Binding();
binding.Converter = this;
myRadioButton.SetBinding(CheckBox.IsCheckedProperty, binding);
I have a piece of code for a Text Box in a XAML File. The text box takes as input Numeric Value.Below is the piece of code:-
<TextBox Text="{Binding Path=Revenue, StringFormat=c0, Mode=TwoWay, Converter={StaticResource NullableConverter}, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Grid.Column="3" Grid.Row="2"/>
However if I input 5 and tab out the input does not become 5 $. However, on saving the data in the page and loading the page the formatting is intact. Any thoughts on this ??
please remove the converter and try it, you should get it. should be something wrong with converter.
this is what I tried for Nullable Converter it worked.
public class NullableConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return 0;
else
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
If you are using SL5 I think this is a bug, the StringFormat is not triggered when the binding is updated. For more details here is the MS connect issue. You can check the workaround it might help you solving the problem.