Reputation: 31
I'm making vocabulary app and trying to implement favorite word in my Xamarin.Forms Listview.
Please have a look below screenshots
For now i use hard code instead of MVVM Here is my model
namespace Mamtil.Models
{
public class Word
{
public int Id { get; set; }
public string word { get; set; }
public string translation { get; set; }
public string audio { get; set; }
public bool favorite { get; set; }
public string groupBy => translation[0].ToString().ToUpper();
}
}
XAML
...
<ViewCell>
<StackLayout Orientation="Horizontal">
<Button x:Name="FavoriteButton" Image="gray_star.png" BackgroundColor="#F5F5F5" Clicked="Favorite" BorderRadius="0" WidthRequest="45" CommandParameter="{Binding .}" />
<Switch IsToggled="{Binding favorite}" WidthRequest="50"/>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" Margin="5, 0, 0, 0">
<Label Text="{Binding translation}">
<Label.FontSize>
<OnPlatform x:TypeArguments="x:Double" iOS="11" Android="18" />
</Label.FontSize>
</Label>
<Label Text="{Binding word}" TextColor="#1565C0">
<Label.FontSize>
<OnPlatform x:TypeArguments="x:Double" iOS="11" Android="13" />
</Label.FontSize>
</Label>
</StackLayout>
<Button x:Name="SpeechButton" Image="ic_mic_black_24dp.png" BackgroundColor="#F5F5F5" Clicked="GoToSpeach" BorderRadius="0" WidthRequest="45" CommandParameter="{Binding Id}" />
</StackLayout>
</ViewCell>
So the question is when i load data from database how do i initialize Image of FavoriteButton like
<!-- Here switch is toggled or not depending on Binding value. I want to do something like this but with image of Button -->
<Switch IsToggled="{Binding favorite}">
in code above it is hard coded but i want to change depending Word.favorite value. At run time i managed to change Image like this
async void Favorite(object sender, EventArgs e)
{
var b = (Button)sender;
Word t = (Word)b.CommandParameter;
//update in database
await App.MamtilRepo.UpdateFavoriteAsync(t.Id);
if (t.favorite)
b.Image = "gray_star.png";
else
b.Image = "yellow_star.png";
t.favorite = !t.favorite;
}
for sake of examle:
...
// Some thing like
if(Word.favorite)
Image = yellow_star.png;
else
Image = gray_star.png;
should i do it some where in code or in XAML
I hope could clearly describe my question. thanks in advance
Upvotes: 1
Views: 1069
Reputation: 1946
DataTrigger or Converter are best solution for your problem.
<Button Image="gray_star.png">
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding favorite}" Value="True">
<Setter Property="Image" Value="yellow_star.png" />
</DataTrigger>
</Button.Triggers>
</Button>
Upvotes: 0
Reputation: 329
an old post, but here's another way to do this. Classically one would use a converter for this. So your button XAML would now look something like this:
<Button x:Name="FavoriteButton" Image="{Binding favorite, Converter={x:Static converter:FavoriteButton.Instance}}" BackgroundColor="#F5F5F5" Clicked="Favorite" BorderRadius="0" WidthRequest="45" CommandParameter="{Binding .}" />
you'd need to add a reference for where your converter lives in the top of your XAML file, i.e.
xmlns:converter="clr-namespace:Mamtil.Converter;assembly=Interact.Client"
With your converter looking something like this:
namespace Mamtil.Converter {
public class FavoriteButton : IValueConverter {
// this Instance property just means your converter only needs to get created once, I saw it in a Xamarin sample.
public static FavoriteButton Instance = new FavoriteButton();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (value == null) {
// only doing this because I've had encounters where an ImageSource has taken Exception at having null returned.
return ImageSource.FromFile("gray_star.png");
}
var fav = (bool)value;
if (fav == true) { // redundant ==, but it makes it quite explicit for any future reader glancing over your code what you intend here.
return ImageSource.FromFile("yellow_star.png");
}
return ImageSource.FromFile("gray_star.png");
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
}
If you're using embedded resources rather than local files then refer to the link Rohit posted in his answer on Aug 24 '16 for how guidance on how to use those in your converter instead.
Upvotes: 1
Reputation: 335
You'd have to use the OnPropertyChanged()
method so that it picks up the new value for the image Url, and you should also set up the binding context.
private bool _imageUrl;
public bool ImageUrl
{
get { return _imageUrl; }
set { _imageUrl = value; OnPropertyChanged(); }
}
And use BindingContext = this;
in your constructor.
Upvotes: 2
Reputation: 11787
You can Bind your Image's Source
to File, Uri or Resource, which sets the image to display.
XAML :
<Image Source="{Binding MyImage}" />
ViewModel :
public ImageSource MyImage {get; set; }
You can read more about working with Images here.
Upvotes: 0