Xamarin Persistent color chooser - c#

I make a button and Color picker to xamarin.forms app, but I want to make it when I choose one color (ex. red) and close app, when i reopen it to see this red color automatic picked. I try to use this code but Preferences not working with Color:
public Color ColorPicker
{
get => Preferences.Get(nameof(ColorPicker), color.Red);
set
{
Preferences.Set(nameof(ColorPicker), value);
OnPropertyChanged(nameof(ColorPicker));
}
}
Can someone help me?

You can store Xamarin.Forms.Color as a string like this:
public string ColorPicker
{
get => Preferences.Get(nameof(ColorPicker), Color.Red.ToString());
set
{
Preferences.Set(nameof(ColorPicker), value);
OnPropertyChanged(nameof(ColorPicker));
}
}
Then you can bind it for instance to Label like this:
<Label TextColor="{Binding ColorPicker}" />
Make sure you set BindingContext in your view. You can read more about Binding here.

The Color.FromHex(string value) method needs a string type parameter. Try to convert the value to string type in the custom class.
Check the code:
Custom Converter class
public class StringToColorConverter : IValueConverter, INotifyPropertyChanged
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var color = Color.FromHex(value as string);
return color;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Page.xaml
<ContentPage.Resources>
<local:StringToColorConverter x:Key="myConverter" />
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout BackgroundColor="{Binding Color_string, Converter={StaticResource myConverter}}">
...
</StackLayout>
</ContentPage.Content>

I is not possible to make it like this. Because i need to use converter after to make string=>color. I am trying this:
public class StringToColor : IValueConverter
{
ColorTypeConverter converter = new ColorTypeConverter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//return value.ToString(); //not working
//return (Color)(converter.ConvertFromInvariantString(value.ToString())); //not working
return Color.FromHex(value.ToString()); //not working too
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
and add this convetor to xaml
<ContentPage.Resources>
<ResourceDictionary>
<local:StringToColor x:Key="str" />
</ResourceDictionary>
</ContentPage.Resources>
<Label Text="TEST" FontSize="Title" TextColor="{Binding ColorPicker,
Converter={StaticResource str}}"/>
but nothing happend...

Related

How to implement Binding for ImageButtons so that the image is only displayed once the image is loaded?

I have two ImageButtons which should switch their images when clicked.
<ImageButton
Grid.Column="15"
Grid.Row="20"
Clicked="Clicked"
Source="{Binding Game[0], Converter={StaticResource StringToSourceConverter}}"
>
</ImageButton>
<ImageButton
Grid.Column="15"
Grid.Row="20"
Clicked="Clicked"
Source="{Binding Game[1], Converter={StaticResource StringToSourceConverter}}"
>
</ImageButton>
The Clicked method swaps the Sources in my Game array and activates INotifyPropertyChanged. It all works out fine. I would just like to know how to implement, that the image should only bind if the image is loaded. Because as you see in the following Images there is a short period where no image is displayed. It's short but it is annoying. The ImageSource is an EmbeddedResource.
I'm wondering if you are using Embedded images or just Local images ? Local images is recommended .
What's more , there is another way to implement this function(swap the image by clicking the button).
Add a bool property in viewmodel.
public class ViewModel : BaseViewModel
{
private bool _isOne;
public bool isOne {
get
{
return _isOne;
}
set
{
_isOne = value;
NotifyPropertyChanged();
}
}
}
Add two Converter for the two ImageButton .
public class FirstConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool isOne = (bool)value;
return isOne ? "a.jpg" : "b.jpg";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return true;
}
}
public class SecondConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool isOne = (bool)value;
return isOne ? "b.jpg" : "a.jpg";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return true;
}
}
Create binding on the ImageButton .
<ContentPage.Resources>
<ResourceDictionary>
<local:FirstConverter x:Key="first" />
<local:SecondConverter x:Key="second" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<ImageButton Clicked="ImageButton_Clicked" Source="{Binding isOne, Converter={StaticResource first}}"/>
<ImageButton Clicked="ImageButton_Clicked" Source="{Binding isOne, Converter={StaticResource second}}"/>
</StackLayout>
Change the property in Button Click event.
private void ImageButton_Clicked(object sender, EventArgs e)
{
model.isOne = !model.isOne;
}

How to bind a modified property to a control Windows Universal Apps (XAML/C#)

I am working on a windows universal app and I'm trying to work out data binding.
I have a listview which has an item template and data template in which a property of a custom class is bound.
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Textblock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This works fine an displays the names all instances of my custom class in the ObservableCollection I bind to the listview. I was wondering however if there is some way of modifying what is being bound before it is bound without changing the class itself.
I'm trying to bind a capitalisation of the string property Name so if the name was Test I want to bind TEST instead. Currently the way I'm doing this is to have a separate property called NameLabel which I populate like this
NameLabel = Name.ToUpper();
However this seems very messy and I was wondering if there's a neater way of doing it without creating a separate property?
You can use a Converter.
Create a StringToUpper.cs File with a StringToUpper Class which inherits form IValueConverter:
public class StringToUpper: IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
var valueString = value.ToString();
if (!string.IsNullOrEmpty(valueString))
{
return valueString.ToUpper();
}
return string.Empty;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
// do nothing.
}
}
Add the resource of your created Converter:
...
xmlns:converter="clr-namespace:StringToUpper"
...>
<Window.Resources>
<converter:StringToUpper x:Key="StringToUpperConverter" />
</Window.Resources>
Add the converter:
<Textblock Text="{Binding Name, Converter={StaticResource StringToUpperConverter}}"/>
Here is a good Tutorial about Converters in WPF.
You could create a converter, that turns the value of a property into a form desired for the view (in your case, a simple capitalisation of the string).
Your converter class might look like this:
public class StringToUpperStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var valueString = value.ToString();
if (!string.IsNullOrEmpty(valueString))
{
return valueString.ToUpper();
}
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Your xaml might have this defined in the resource section:
<converters:StringToUpperStringConverter x:Key="StringToUpperStringConverter" />
And your binding would then look like this:
<Textblock Text="{Binding Name, Converter={StaticResource StringToUpperStringConverter}}"/>

Philosophy on Binding to Parameters in WPF

So I'm trying to build out a project that will allow a user to type some text into a textbox on the left side of the form and that will filter out the available items from my datasource list.
<Label Content="Enter item name below"></Label>
<TextBox Name="SearchTermTextBox" TabIndex="0" Text="" />
I was under the impression I could bind to the datasource the list then use a converter to filter out the items that were unlike the string.
<ListBox DataContext="{Binding Colors}">
<ListBox.ItemsSource>
<MultiBinding Converter="{StaticResource FilterTextValueConverter}" ConverterParameter="{Binding ElementName=SearchTermTextBox, Path=Text}" />
</ListBox.ItemsSource>
<ListBox.ItemTemplate>
//etc...
</ListBox.ItemTemplate>
</ListBox>
However, you can't bind to an elementname in the converterparameter unless you use something called a dependency property.
Edit: Seeing as I've created confusion with the code above, here's the converter I'm trying to bind:
public class FilterTextValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var trackedColors = value as List<Colors>;
if (trackedColors != null)
return (trackedColors).Where(item => item.ColorName.Contains(parameter.ToString())).ToList();
return null;
}
public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class Colors
{
public String ColorName;
public String Description;
}
What is wrong with my approach here? Clearly I'm angering the WPF gods since this is a fairly straightforward operation but I'm being denied it on principle. Any help would be appreciated.
Simple binding with converter will work here, no need for MultiBinding.
<ListBox ItemsSource="{Binding Path=Text, ElementName=SearchTermTextBox,
Converter="{StaticResource FilterTextValueConverter}">
......
</ListBox>
Assuming FilterTextValueConverter is implementing IValueConverter, you can access text from value passed to Convert method.
public class FilterTextValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
string text = value.ToString(); // TEXT for textBox can be accessed here.
return new List<string>(); // Return filtered list from here.
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
UPDATE
In case you want to pass multiple bindings to converter, use IMultiValueConverter because ConverterParameter is not Dependency property, hence cannot be bound.
XAML
<ListBox DataContext="{Binding Colors}">
<ListBox.ItemsSource>
<MultiBinding Converter="{StaticResource FilterTextValueConverter}">
<Binding/>
<Binding ElementName="SearchTermTextBox" Path="Text"/>
</MultiBinding>
</ListBox.ItemsSource>
</ListBox>
Converter
public class FilterTextValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
var trackedColors = values[0] as List<Colors>;
if (trackedColors != null && !String.IsNullOrEmpty(values[1].ToString()))
return (trackedColors).Where(item =>
item.ColorName.Contains(values[1].ToString())).ToList();
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I continued looking into this issue well after the accepted answer was posted and working for me. What I discovered is that it's a fairly trivial task to wrap the control you're trying to get a new dependencyproperty out of to allow for proper binding.
I will not be accepting my own answer to this determined so much later, but this seems (in my amateur opinion) like a much more elegant solution than adding a converter despite being a bit more complex:
Note that this is for a new dependency on the caretindex property of a textbox, not for the original question on binding, but it just requires some smart renaming to get it working ;).
public class TextBoxDependencyWrapper : TextBox
{
public static readonly DependencyProperty CaretIndexProperty = DependencyProperty.Register(
"CaretIndex", typeof (int), typeof (TextBoxDependencyWrapper), new FrameworkPropertyMetadata(default(int), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, CaretIndexChanged ));
protected override void OnKeyUp(KeyEventArgs e) //Event that changes the property we're trying to track
{
base.OnKeyUp(e);
CaretIndex = base.CaretIndex;
}
protected override void OnKeyDown(KeyEventArgs e) //Event that changes the property we're trying to track
{
base.OnKeyDown(e);
CaretIndex = base.CaretIndex;
}
public new int CaretIndex
{
get { return (int) GetValue(CaretIndexProperty); }
set { SetValue(CaretIndexProperty, value); }
}
}

Set converter on TextBox

I need to calculate/change form of input between textbox to its bindable source. The way i trying to achive this, is with help of converters.
Converter:
public class ParameterConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return string.Empty;
string originalParameValue = value.ToString();
string fixedParameterValue = string.Format("#_{0}", originalParameValue);
return fixedParameterValue;
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
XAML:
<Window.Resources>
<converters:ParameterConverter x:Key="parameterConverter" />
</Window.Resources>
<Grid>
<TextBox Text="{Binding ParameterA, Converter={StaticResource parameterConverter}}"/>
</Grid>
The problem is, that converter is functioning only once. Is it approach correct (i mean with converter) or there are another approaches ?
Perhaps the binding Mode is not two way, and did your property fire property changed.
Does your data context implement INotifyPropertyChanged and is PropertyChanged being called whenever ParameterA is changed? It seems as if nobody is notifying the textbox that it needs to update its contents.

Hide button when label is not empty

I am using WPF.
I want to show button when the label is not empty. When Label has a value, the button will be hidden.
How can I do this with WPF? Using <Style>?
Code:
<Label Name="lblCustomerName"/>
<Button Name="btnCustomer" Content="X" Visibility="Hidden" />
try
if (string.IsNullOrEmpty(lblCustomerName.Text)) {
btnCustomer.Visibility = Visibility.Hidden;
}
else {
btnCustomer.Visibility = Visibility.Visible;
}
You will need to use a converter and bind it to the content of lblCustomer.
public class ContentNullToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return Visibility.Hidden;
}
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
More on converters here.
Then in xaml you can do the following:
First line needs to be defined in your resources where you will need to qualify it with the namespace in which you created the class above. Once you have defined the resource you can use the second part.
<ContentNullToVisibilityConverter x:Key="visConverter"/>
<Label Name="lblCustomerName"/>
<Button Name="btnCustomer" Content="X" Visibility="{Binding ElementName=lblCustomer, Path=Content, Converter={StaticResource visConverter}}" />

Categories