Xamarin forms eventToCommand behavior for zxing library - xamarin

i'm trying to use the event to command behavior for the zxing barcode scanning.
var eventParameters = eventinfo.EventHandlerType
.GetRuntimeMethods().First(m => m.Name == "Invoke")
.GetParameters()
.Select(p => Expression.Parameter(p.ParameterType))
.ToArray();
var actionInvoke = action.GetType()
.GetRuntimeMethods().First(m => m.Name == "Invoke");
_handler = Expression.Lambda(
eventinfo.EventHandlerType,
Expression.Call(Expression.Constant(action), actionInvoke, eventParameters[0], eventParameters[1]),
eventParameters).Compile();
eventinfo.AddEventHandler(item, _handler);
this code works fine for any other event that has (object sender and event args) but the zxing event has only one argument. Do u know how can i make this code to work?

The EventToCommandBehavior will probably pass arguments as object type.
Add this the your eventToCommandBehavior
public static BindableProperty EventArgsConverterProperty = BindableProperty.CreateAttached("EventArgsConverter", typeof(IValueConverter), typeof(EventToCommandBehavior), null, BindingMode.OneWay);
...
public IValueConverter EventArgsConverter
{
get { return (IValueConverter)GetValue(EventArgsConverterProperty); }
set { SetValue(EventArgsConverterProperty, value); }
}
...
This is the implementation of YourEventArgsConverter.
public class YourEventArgsConverter : IValueConverter
{
public object Converter(object value, Type, targetType, object parameter, CultureInfo culture)
{
var eventArgs = value as [PUT YOUR EVENT ARGS TYPE HERE];
if (eventArgs == null)
throw new ArgumentException("Expected YOUR EVENT ARGS TYPE as value", value)
return eventArgs;
}
public object ConvertBack(object value, Type, targetType, object parameter, CultureInfo culture)
{
throw new NoImplementedException();
}
}
You can use the EventArgsConvert like this.
...
<ResourceDictionary>
<converters:YourEventArgsConverter x:Key="YourEventArgsConverter" />
</ResourceDictionary>
...
<behaviors:EventToCommandBehavior
EventName="YOUREVENTNAME"
EventArgsConverter="{StaticResource YourEventArgsConverter}"
Command="{Binding EventCommand}" />
...

Related

Xamarin.Forms: MultiBinding IMultiValueConverter recieving Null values

Hello Guys i need help.
i am using a converter on a binding to set a background color depending on an object id.(stacklayout inside contentview)
<StackLayout.BackgroundColor>
<Binding Path="objectID" Converter="{StaticResource IntToColorConverter}"/>
</StackLayout.BackgroundColor>
This works.
Now i want to use the multiconverter (new in Xamarin 4.7) to return a different backgroundcolor depending on other object properties.(for context: object is a calendarentry and if its in the past it should be desaturated or something)
<StackLayout.BackgroundColor>
<MultiBinding Converter="{StaticResource MultiColorConverter}">
<Binding Path="objectID"/>
<Binding Path="value"/>
<Binding Path="value2"/>
</MultiBinding>
</StackLayout.BackgroundColor>
This does not work, since the values that are given to the converter are all NULL and the color becomes black (the return value if all vslues are NULL; so the converter is set up correctly also). It also shows this when i use a break point on the converter, that the array contains only NULL variables.
I don't know what i am missing here, the bindingcontext should be inheritated and does not change. Any hint would be appreciated.
The bindingcontext is set programatically on a contentpage on creation of the ContentView where i provide an object from a list of objects.
var evnt = new TimeTableEventView { BindingContext = Model.calenderevents[j] };
You need to return BindableProperty.UnsetValue to use the binding FallbackValue .
in xaml
<StackLayout.BackgroundColor>
<MultiBinding Converter="{StaticResource MultiColorConverter}">
<Binding Path="red"/>
<Binding Path="green"/>
<Binding Path="blue"/>
</MultiBinding>
</StackLayout.BackgroundColor>
in Converter
public class MultiColorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
foreach (var value in values)
{
if (!(value is int b))
{
return Color.White;
// set a default value when unset
}
}
int red = (int)values[0];
int green = (int)values[1];
int blue = (int)values[2];
Color color = Color.FromRgb(red,green,blue);
return color;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
in code behind
public class MyViewModel
{
public int red { get; set; }
public int green { get; set; }
public int blue { get; set; }
public MyViewModel(int r, int g, int b)
{
red = r;
green = g;
blue = b;
}
}
BindingContext = new MyViewModel(120, 60, 180);

Xamarin Forms Entry Binding two way with nullable decimal does not allow to put decimal point

I have an Entry which is binded two way with nullable decimals and has numeric keyboard. Everything is ok except I cannot use decimal point. Whenever I press . (dot) from keyboard, UI does not accept it. Do you guys have any idea? Online search did not help me. Thanks. BTW, I use Android Emulator.
I found out that if I change property from nullable to non-nullable (i.e decimal? to decimal) then UI accepts decimal point. Do you guys have any idea why? Why UI does not allow to enter decimal point when the binding property is nullable?
This is because the value is not recognized with a defined type while it is incomplete (editing).
You can use a converter (String to double) like this:
>
public class DoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
return (double)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
string stringValue = value as string;
if (string.IsNullOrEmpty(stringValue))
return null;
double dbl;
if (double.TryParse(stringValue, out dbl))
{
if(dbl == 0)
{
return null;
}
return dbl;
}
return null;
}
}
Reference:
https://forums.xamarin.com/discussion/60719/xamarin-forms-binding-nullable-double-to-entry

How to change appearance of viewcell using bound data in Xamarin Forms?

What i am trying to do is, I created a ViewCell and bound it to ListView. In ViewCell, I have title label which I want to change as per data coming from the database.
What would be the best practice to this?
Here my chunk of code
Model-
public class helplineservices
{
public string title { get; set; }
public bool isenable { get; set; }
}
ViewCell -
public class HelpLineCell : ViewCell
{
#region binding view cell logic
public HelpLineCell()
{
BlackLabel title = new BlackLabel
{
FontFamily = Device.OnPlatform(
"Roboto-Black",
null,
null),
FontSize = Device.OnPlatform(
(ScreenSize.getscreenHeight() / 47),
(ScreenSize.getscreenHeight() / 47),
14
),
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Color.FromHex("#FFFFFF"),
WidthRequest = ScreenSize.getscreenWidth()
};
title.SetBinding(Label.TextProperty, "title");
this.View = title;
}
#endregion
}
ListView -
var HelpList = new ListView
{
IsPullToRefreshEnabled = true,
HasUnevenRows = true,
BackgroundColor = Color.Transparent,
RefreshCommand = RefreshCommand,
//row_list is a list that comes from database
ItemsSource = row_list,
ItemTemplate = new DataTemplate(typeof(HelpLineCell)),
SeparatorVisibility = SeparatorVisibility.None
};
I want to change title color by checking a bool value of isenable which comes from database.
Please help me.
You have to Bind the TextColor like you have done for your Text property, then convert with a IValueConverter the Boolean value to a Color
Something like:
title.SetBinding(Label.TextColorProperty, new Binding("isenable", BindingMode.Default, new BooleanToColorConverter()));
Your IValueConverter should be something like
public class BooleanToColorConverter : IValueConverter
{
#region IValueConverter implementation
public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is bool) {
if(((bool) value) == true)
return Color.Red;
else
return Color.Black;
}
return Color.Black;
}
public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException ();
}
#endregion
}
PS: NOT TESTED...
A useful article

WP 8.1 Binding image from a http request

I have a ListView item which contains datas and images from a http GET request. I can display all of data in the ListView, except the picture. For getting the image I have to make a separate http GET request. I can display an image with this code:
private async void DisplayPicture()
{
var ims = new InMemoryRandomAccessStream();
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(App.answer.picture);
await dataWriter.StoreAsync();
ims.Seek(0);
BitmapImage bitmap = new BitmapImage();
bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmap.SetSource(ims);
}
But this doesn't work if I would like to use in a ListView with Binding.
Here is the code what I tried:
public class BinaryToImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value != null && value is byte[])
{
var bytes = value as byte[];
var ims = new InMemoryRandomAccessStream();
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(bytes);
//await dataWriter.StoreAsync();
ims.Seek(0);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(ims);
//var ims = new MemoryStream(bytes);
//var image = new BitmapImage();
//image.SetSource(stream);
//stream.Close();
return bitmap;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
The main problem is that I get the image in byte[] (bytearray) from the server, and only the above code can display it on WP8.1. So I have to use the dataWriter.StoreAsync() method, but if I use it, I have to use async, which must be void. But the void return value is not good for me due to the binding.
You can see the original code what I uncommented, but I cannot use it, because the input value for image.SetSource() must be a RandomAccessStream. So I don't have any idea how I can solve this problem.
If you want to make binding and use asynchronous method, then one way to make it work is to set DataContext to Task and bind to its Result. Stepen Cleary wrote a nice article about that. You will also find some useful information in his answer here.
Basing on that answer I've build a sample, which I think you can modify to fulfill your needs. Write a Converter which will return TaskCompletionNotifier (see Stephen's answer above):
public class WebPathToImage : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null) return null;
// the below class you will find in Stephen's answer mentioned above
return new TaskCompletionNotifier<BitmapImage>(GetImage((String)value));
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{ throw new NotImplementedException(); }
private async Task<BitmapImage> GetImage(string path)
{
HttpClient webCLient = new HttpClient();
var responseStream = await webCLient.GetStreamAsync(path);
var memoryStream = new MemoryStream();
await responseStream.CopyToAsync(memoryStream);
memoryStream.Position = 0;
var bitmap = new BitmapImage();
await bitmap.SetSourceAsync(memoryStream.AsRandomAccessStream());
return bitmap;
}
}
then you can define binding in XAML:
<Image DataContext="{Binding ImageFromWeb, Converter={StaticResource WebPathToImage}}" Stretch="Uniform"
Source="{Binding Result}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="2"/>
Everything should work when you set ImageFromWeb:
ImageFromWeb = #"http://www.onereason.org/wp-content/uploads/2012/02/universe-300x198.jpg";

Data Binding for images using sql ce for windows phone 7

I have been using the sql ce to bring some data onto my application. Now I need to add some of the images to make it look pretty. What all I want to know is
There must be some image to byte conversion done,
Retrieve the image byte code and convert back into the image.
I've got stuck at the second part and how am I supposed to continue?
Any links or examples are needed for the reference.
Thanks a lot.
Here's some ideas I have used in the past.
The image column in the DB:
[Column]
public byte[] MyImage
{
get { return _myImage; }
set
{
if (_myImage != value)
{
_myImage = value;
NotifyPropertyChanging("MyImage");
NotifyPropertyChanged("MyImage");
}
}
}
Save image:
public void AddNewImage(Stream image, string url)
{
byte[] byteArray = GetImageBytes(image);
var item = new MyDatabaseItem { Count = 1, ItemImageUrl = url, MyImage = byteArray };
MyDatabaseItemModel.Add(item);
MyDatabaseDB.MyDatabaseItems.InsertOnSubmit(item);
MyDatabaseDB.SubmitChanges();
}
Get image:
private byte[] GetImageBytes(Stream stream)
{
using (var ms = new MemoryStream())
{
var writeableBitmap = PictureDecoder.DecodeJpeg(stream, 200, 200);
writeableBitmap .SaveJpeg(ms, 200, 200, 0, 30);
return ms.ToArray();
}
}
Using a value converter:
public class ImageConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is byte[])
{
var memoryStream = new MemoryStream(value as byte[]);
varwriteBitmap = PictureDecoder.DecodeJpeg(memoryStream, 200, 200);
return writeBitmap;
}
else
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And finally bind it in XAML:
<Image Source="{Binding MyImage, Converter={StaticResource ImageConverter}}" Stretch="UniformToFill"/>

Resources