RSS-reader that keeps unread items - windows-phone-7

So I have a simple RSS-reader, that has a feed that gets updated when the app is started. How can I add functionality that keeps the new unread items in a different color? I would like to make it visible for the user which posts are new since last time he/she opened the app.

Presuming you have a model something like;
public class RSSItem {
public bool IsUnread { get; set; }
public string Title { get; set; }
}
You'll want to bind the ForegroundColor of a TextBlock to your IsUnread property using a IValueConverter that takes a bool and returns a Color. So your XAML might look like;
<phone:PhoneApplicationPage.Resources>
<converters:UnreadForegroundConverter x:Key="UnreadForegroundConverter" />
</phone:PhoneApplicationPage.Resources>
<ListBox x:Name="RSSItems">
<DataTemplate>
<TextBlock Text="{Binding Title}" Foreground="{Binding IsUnread, Converter={StaticResource UnreadForegroundConverter}}" />
</DataTemplate>
</ListBox>
Don't forget to add the xmlns:converters attribute to your Page's tag.
You'll then want to implement your IValueConverter to do the boolean to colour conversion;
public class UnreadForegroundConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
if ((bool)value == true) {
return Application.Current.Resources["PhoneAccentColor"];
}
return Application.Current.Resources["PhoneForegroundColor"];
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
}
And obviously you'll need to bind the listbox, RSSItems, to a collection of RSSItem. Eg.
ObservableCollection<RSSItem> items = new ObservableCollection<RSSItem>();
// populate items somehow
RSSItems.ItemsSource = items;
Hope that helps.

Related

If image not found skip record in ListView Xamarin Forms

I have a dynamically created ListView. I would like if the image is not found it skips that row. I'm not sure if that is doable, but I only want to display item with images.
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout x:Name="{Binding Name}"
Orientation="Horizontal"
Padding="5">
<Image x:Name="categoryImage" Source="{Binding ImageID, Converter={StaticResource converter}}"
Aspect="AspectFit"
WidthRequest="130"/>
<Label x:Name="categoryLabel" Text="{Binding Description}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Value converter
public class ImagePostValueConverter : IValueConverter
{
public int source { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var source = (int)value;
if (source == 0)
return null;
var imageSource = ImageSource.FromResource($"ERPProject.AllImages.MyImages.ea_{source }.png", typeof(ImagePostValueConverter).GetTypeInfo().Assembly);
return imageSource;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I am pulling these images from a folder in my PCL library. Not really sure how to accomplish this.
EDIT: SOLVED
if anyone has this problem I figured out a working solution. Lucas Zhang helped me come to this solution but I tweaked it to work for me.
Essentially I did create a whole new valueconverter and Binded the true or false to the IsVisible attribute for the stacklayout. However sine I am passing in the ImageID which is the ID of the record, i just use the recordID as the ImageID as well that is how my images are named.. (e.g. image_ID.png so Image_1.png) 0 doesn't exist like assumed in Lucas' answer. I used Assembly.GetExecutingAssembly().GetManifestResourceStream(myPathtoImage);
put that in a variable and then see if the variable is null. If it is then I return false.else return true and display the item in the listview.
You could binding the IsVisible
<StackLayout x:Name="{Binding Name}"
Orientation="Horizontal"
Padding="5"
IsVisible="Binding ImageID, Converter={StaticResource IsVisibleConverter}}"
>
<Image x:Name="categoryImage" Source="{Binding ImageID, Converter={StaticResource converter}}"
Aspect="AspectFit"
WidthRequest="130"/>
<Label x:Name="categoryLabel" Text="{Binding Description}"/>
</StackLayout>
in Converter
public class IsVisibleConverter: IValueConverter
{
public int source { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var source = (int)value;
if (source == 0)
return false;
else
return true;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Toggle button with an image in xamarin

i am using Button as beow to show the add to cart button with image in the xaml view
<Button x:Name="cartbutton" Grid.Row="0" Command="{Binding Source={x:Reference ListItemPage}, Path=BindingContext.CartCommand}" CommandParameter="{Binding .}" HorizontalOptions="End" VerticalOptions="Start" Image="lowim.png" BackgroundColor="Transparent" Margin="0,5,5,0" />
and use in the MVVM inside the constructor as below
CartCommand = new Command<Resturent>(OnCartCommand);
then i am using MVVM with dependency injection where i only get the Icommand of the button click in the view model as below
public ICommand CartCommand { get; set; }
public async void OnCartCommand(Resturent restoraunt)
{
await DialogService.DisplayAlert("CART DETAILS", "ITEM"+ restoraunt.Name+ "SUCESSFULLY ADDED", "OK");
}
i am expecting to create a toggle button where when i click on the button ( where the user add the items to the cart by pressing button with image lowim.png as shown above) then the image of the button suppose to change ( with another image icon lets say add.jpg). support in this regard will be highly appreciated and thank you advance for your support.
Well, all you have to do is create a converter something like this:
public class ConverterAddRemoveImage : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool isAddedToCart = (bool)value;
if (isAddedToCart)
{
return "PositiveImage"; //This will be a string
}
else
{
return "NegativeImage"; //This will be a string
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then you need to define it in the XAML resource dictionary of your XAML page something like this:
<ContentPage.Resources>
<ResourceDictionary>
<common:ConverterAddRemoveImage x:Key="AddRemoveImage" />
</ResourceDictionary>
</ContentPage.Resources>
Where common is the namespace where your converter is present.
The image source would be something like this:
Source="{Binding IsAddedToCart, Converter={StaticResource AddRemoveImage}}
Where is added to cart is a bool property in your model something like this :
private bool isInCart;
public event PropertyChangedEventHandler PropertyChanged;
public bool IsAddedToCart
{
get
{
return isInCart;
}
set
{
isInCart= value;
NotifyPropertyChanged(nameof(IsAddedToCart));
}
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Note: Your model class must inherit from INotifyPropertyChanged interface
Now, as soon as you change your model bool property it will change the image accordingly.
Goodluck revert in case of any queries

Entry binding to int? in Xamarin Forms

I have a simple entry in Xamarin Forms:
<Entry Text="{Binding Number, Mode=TwoWay}" Placeholder="Number" Keyboard="Numeric" />
In ViewModel there is property:
private int? _number;
public int? Number
{
get { return _number; }
set
{
if (SetProperty(ref _number, value))
{
OnPropertyChange(nameof(Number));
}
}
}
I enter number in Entry and press button, but in button clicked procedure - Number is still null. What am I doing wrong?
You can bind an int to an Entry but you can't bind a nullable int. You can either add another property which converts the number to a string, or you can easily create a value converter like this...
class NullableIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var nullable = value as int?;
var result = string.Empty;
if (nullable.HasValue)
{
result = nullable.Value.ToString();
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var stringValue = value as string;
int intValue;
int? result = null;
if (int.TryParse(stringValue, out intValue))
{
result = new Nullable<int>(intValue);
}
return result;
}
... and use it in your page like this...
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:IntBinding"
x:Class="IntBinding.DemoPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:NullableIntConverter x:Key="NullableIntConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Entry Text="{Binding Number, Mode=TwoWay, Converter={StaticResource NullableIntConverter}}" Placeholder="Number" Keyboard="Numeric" />
<Label Text="{Binding Number, Converter={StaticResource NullableIntConverter}}" />
</StackLayout>
</ContentPage>
Entry accept a string. If you would like to bind a int property you should use a IValueConverter but I think the best solution is to use a String property than convert the value from String to Int
public string StrNumber{
get {
if (Number == null)
return "";
else
return Number.ToString();
}
set {
try {
Number = int.Parse(value);
}
catch{
Number = null;
}
}
}
public string MP { get; set; }
public float MainPrice => (float.TryParse(MP, out float mp)) ? mp : 0;

Call converter depending on two values

i'm trying to get a value depending two values, in my listbox i'm trying to do somthing like this :
<TextBlock x:Name="Distance" Text="{Binding lattitude,Longtitude,Converter={StaticResource Distanceconverter}}" />
so, actually the problem that i need to call my converter but depending in 2 values,
any ideas please?
Yeah, change to what you are binding to the following:
<TextBlock x:Name="Distance" Text="{Binding Path=.,Converter={StaticResource Distanceconverter}}" />
And change your DistanceConverter to accept the object which contains both the latitude and longitude. Multi binding is not currently supported in Windows Phone.
At the top of your page, add:
<phone:PhoneApplicationPage.Resources>
<converters:Distanceconverter x:Key="Distanceconverter" />
</phone:PhoneApplicationPage.Resources>
Assuming your binding model looks like:
public class LocationModel
{
public double Longitude { get; set; }
public double Latitude { get; set; }
}
Create a converter in the form of
public class DistanceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var location = value as LocationModel;
if (location != null)
{
// Your business logic here, e.g.
return location.Latitude + location.Latitude;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Bind list of images to StackPanel

i want to bind a list of images to a stackpanel which is inside a DataGrid.RowDetailsTemplate.
My class structure is as follows:
public class A
{
private List<MyImage> _images = new List<MyImage>();
public List<MyImage> Images { get; set; }
public string Name { get; set; }
public void AddImage(byte[] src) { ... }
}
public class MyImage
{
public BitmapImage Image { get; set; }
public byte[] RawData { get; set; }
}
In my main class i have a list of A:
public List<A> AList { get; set; }
dataGrid1.ItemsSource = AList;
dataGrid1.DataContext = AList;
All i want to do is to display the Name property of an element in a DataGridTextColumn and all images stored in the Images property in the RowDetails.
My xaml is:
<DataGrid name="dataGrid1">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Path=Name}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel DataContext="{Binding Path=Images}">
<Image Source="{Binding Path=RawData}"/>
</StackPanel>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
All i get to see is just one image although there are some more stored in Images. Any ideas?
Ok, so the solution of this problem was the use of ContentPresenter combined with a converter.
Now my XAML looks like this:
<DataGrid name="dataGrid1">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Path=Name}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Images, Converter={StaticResource ImageCollectionConverter}}"/>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
And the corresponding converter class:
public class ImageCollectionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
List<MyImage> images = value as List<MyImage>;
if (images != null)
{
StackPanel stack = new StackPanel();
stack.Orientation = Orientation.Horizontal;
foreach (DesignImage img in images)
{
Image image = new Image();
image.Source = img.Image;
stack.Children.Add(image);
}
return stack;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Resources