What I need:
A DataTemplate of Image, Title, Description.
What I tried:
I tried ImageCell but it's image size cannot be controlled and hence the Image goes out of screen (on Windows Phone 8.1)
I tried creating CustomRenderer, wasn't able to do it for WP8.1 (couldnt extract the UI Controls from DataTemplate in public override Windows.UI.Xaml.DataTemplate GetTemplate(Cell cell)
I created a ViewCell.View, put Image + two Labels in a Grid. BUT again, it doesnt work properly on WP8.1. When I scroll back up, the Text gets cut.
<ViewCell>
<ViewCell.View>
<StackLayout Padding="20,10,20,10">
<Grid ColumnSpacing="10" RowSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Label Text="{Binding Title}"
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="Medium"
XAlign="Start" HorizontalOptions="StartAndExpand" YAlign="Start" LineBreakMode="CharacterWrap" MinimumHeightRequest="60"
FontAttributes="Bold"
TextColor="Black">
</Label>
<Image Source="{Binding Image}"
Grid.Row="1" Grid.RowSpan="2" Grid.Column="0"
Aspect="AspectFill" HorizontalOptions="Start">
</Image>
<Label Text="{Binding Description}"
Grid.Row="1" Grid.RowSpan="2" Grid.Column="1"
FontSize="14" XAlign="Start" HorizontalOptions="StartAndExpand" YAlign="Start" LineBreakMode="CharacterWrap"
TextColor="Black">
</Label>
</Grid>
</StackLayout>
</ViewCell.View>
</ViewCell>
So, how do I create my own Cell or Control more attributes of ImageCell
This is a code that I once wrote to make a custom ViewCell, it has a label and an image, hope this helps you (I tested this on iOS, Android and WP):
public class ViewCellExtend : ViewCell
{
Label menuText;
Image menuImagen;
public ViewCellExtend()
{
menuText = new Label();
menuImagen = new Image()
{
Aspect = Aspect.AspectFit,
HeightRequest = 30,
WidthRequest = 30
};
StackLayout stContenedor = new StackLayout
{
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Spacing = 20,
Children =
{
CreateCellBlock()
}
};
View = stContenedor;
}
Xamarin.Forms.Layout CreateCellBlock()
{
StackLayout st2 = new StackLayout
{
Orientation = StackOrientation.Horizontal,
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Children =
{
new StackLayout
{
Padding = new Thickness(15,0,10,0),
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Center,
Children =
{
menuImagen
}
},
new StackLayout
{
Padding = new Thickness(0,5,10,0),
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Center,
Children =
{
menuText
}
}
}
};
st2.SetBinding(Layout.BackgroundColorProperty, new Binding("BackgroundColor"));
return st2;
}
public static BindableProperty BindableTextProperty = BindableProperty.Create<ViewCellExtend, string>(ctrl =>
ctrl.TextProperty,
defaultValue: string.Empty,
defaultBindingMode: BindingMode.TwoWay,
propertyChanging: (bindable, oldValue, newValue) =>
{
var ctrl = (ViewCellExtend)bindable;
ctrl.TextProperty = newValue;
});
public string TextProperty
{
get { return (string)GetValue(BindableTextProperty); }
set
{
SetValue(BindableTextProperty, value);
menuText.Text = value;
}
}
public static BindableProperty BindableImageProperty = BindableProperty.Create<ViewCellExtend, ImageSource>(ctrl =>
ctrl.ImageProperty,
defaultValue: default(ImageSource),
defaultBindingMode: BindingMode.Default,
propertyChanging: (bindable, oldValue, newValue) =>
{
var ctrl = (ViewCellExtend)bindable;
ctrl.ImageProperty = newValue;
}
);
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
System.Diagnostics.Debug.WriteLine(BindingContext.ToString());
}
public ImageSource ImageProperty
{
get { return (ImageSource)GetValue(BindableImageProperty); }
set
{
SetValue(BindableImageProperty, value);
menuImagen.Source = value;
}
}
}
Here's a very good demonstration of using custom ViewCellRenderer:
https://github.com/xamarin/xamarin-forms-samples/tree/master/WorkingWithListviewNative
Android:
public class NativeAndroidCellRenderer : ViewCellRenderer
{
protected override Android.Views.View GetCellCore (Xamarin.Forms.Cell item, Android.Views.View convertView, Android.Views.ViewGroup parent, Android.Content.Context context)
{
var x = (NativeCell)item;
var view = convertView;
if (view == null) {// no view to re-use, create new
view = (context as Activity).LayoutInflater.Inflate (Resource.Layout.NativeAndroidCell, null);
} else { // re-use, clear image
// doesn't seem to help
//view.FindViewById<ImageView> (Resource.Id.Image).Drawable.Dispose ();
}
view.FindViewById<TextView>(Resource.Id.Text1).Text = x.Name;
view.FindViewById<TextView>(Resource.Id.Text2).Text = x.Category;
// grab the old image and dispose of it
// TODO: optimize if the image is the *same* and we want to just keep it
if (view.FindViewById<ImageView> (Resource.Id.Image).Drawable != null) {
using (var image = view.FindViewById<ImageView> (Resource.Id.Image).Drawable as BitmapDrawable) {
if (image != null) {
if (image.Bitmap != null) {
//image.Bitmap.Recycle ();
image.Bitmap.Dispose ();
}
}
}
}
// If a new image is required, display it
if (!String.IsNullOrWhiteSpace (x.ImageFilename)) {
context.Resources.GetBitmapAsync (x.ImageFilename).ContinueWith ((t) => {
var bitmap = t.Result;
if (bitmap != null) {
view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (bitmap);
bitmap.Dispose ();
}
}, TaskScheduler.FromCurrentSynchronizationContext() );
} else {
// clear the image
view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (null);
}
return view;
}
}
iOS:
public class NativeiOSCellRenderer : ViewCellRenderer
{
static NSString rid = new NSString("NativeCell");
public override UIKit.UITableViewCell GetCell (Xamarin.Forms.Cell item, UIKit.UITableViewCell reusableCell, UIKit.UITableView tv)
{
var x = (NativeCell)item;
Console.WriteLine (x);
NativeiOSCell c = reusableCell as NativeiOSCell;
if (c == null) {
c = new NativeiOSCell (rid);
}
UIImage i = null;
if (!String.IsNullOrWhiteSpace (x.ImageFilename)) {
i = UIImage.FromFile ("Images/" + x.ImageFilename + ".jpg");
}
c.UpdateCell (x.Name, x.Category, i);
return c;
}
}
public class NativeiOSCell : UITableViewCell {
UILabel headingLabel, subheadingLabel;
UIImageView imageView;
public NativeiOSCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB (255,255,224);
imageView = new UIImageView();
headingLabel = new UILabel () {
Font = UIFont.FromName("Cochin-BoldItalic", 22f),
TextColor = UIColor.FromRGB (127, 51, 0),
BackgroundColor = UIColor.Clear
};
subheadingLabel = new UILabel () {
Font = UIFont.FromName("AmericanTypewriter", 12f),
TextColor = UIColor.FromRGB (38, 127, 0),
TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
ContentView.Add (headingLabel);
ContentView.Add (subheadingLabel);
ContentView.Add (imageView);
}
public void UpdateCell (string caption, string subtitle, UIImage image)
{
imageView.Image = image;
headingLabel.Text = caption;
subheadingLabel.Text = subtitle;
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
imageView.Frame = new CoreGraphics.CGRect(ContentView.Bounds.Width - 63, 5, 33, 33);
headingLabel.Frame = new CoreGraphics.CGRect(5, 4, ContentView.Bounds.Width - 63, 25);
subheadingLabel.Frame = new CoreGraphics.CGRect(100, 18, 100, 20);
}
}
Hi All i have a list box and i am saving list box selected item in XML file thats working fine but the problem is that when i will close my app and reopen and add more value to list box my previous value is removed form the xml file and listbox also how i can save my current added value and previous value in xml file i am using following code :
and iam using following code
<Grid x:Name="ContentPanel" Grid.Row="2" Margin="15,10,15,0">
<ListBox Name="list_location" Tap="list_location_Tap" Foreground="Black">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="item_name" Text="{Binding description, Mode=OneWay}" Padding="5,15,5,15" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeLarge}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="list_locationAdd" Background="Red" Foreground="Black" Visibility="Collapsed">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="item_name" Text="{Binding description, Mode=OneWay}" Padding="5,15,5,15" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeLarge}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
and my back end code is follow:
XmlWriterSettings x_W_Settings = new XmlWriterSettings();
x_W_Settings.Indent = true;
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = ISF.OpenFile(filename, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<Prediction>));
using (XmlWriter xmlWriter = XmlWriter.Create(stream, x_W_Settings))
{
data.Add(new Prediction() { description = App.professionalId });
list_locationAdd.ItemsSource = data;
serializer.Serialize(xmlWriter, data);
}
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
try
{
if (list_locationAdd != null)
{
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream str = ISF.OpenFile(filename, FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<Prediction>));
ObservableCollection<Prediction> data = (ObservableCollection<Prediction>)serializer.Deserialize(str);
if (list_locationAdd != null)
{
this.list_locationAdd.ItemsSource = data;
list_locationAdd.Visibility = Visibility.Visible;
}
}
}
}
}
catch (Exception ex)
{
}
}
Change in your code as per below :
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = ISF.OpenFile(filename, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<Prediction>));
using (XmlWriter xmlWriter = XmlWriter.Create(stream, x_W_Settings))
{
data.Add(new Prediction() { description = App.professionalId });
list_locationAdd.ItemsSource = data;
serializer.Serialize(xmlWriter, data);
}
}
Update in your current code :
IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);
if (isoStore.FileExists(filename))
{
try
{
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read, isoStore))
{
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<Prediction>));
ObservableCollection<Prediction> data = (ObservableCollection<Prediction>)serializer.Deserialize(isoStream);
this.list_locationAdd.ItemsSource = data;
}
}
catch(Exception ex)
{ }
}
else
{
try
{
using (IsolatedStorageFileStream isoStream = new IsolatedStorageFileStream(filename, FileMode.Create, isoStore))
{
XmlSerializer Serialize = new XmlSerializer(typeof(ObservableCollection<Prediction>));
using (XmlWriter writer = XmlWriter.Create(isoStream, x_W_Settings))
{
data.Add(new Prediction() { description = App.professionalId });
list_locationAdd.ItemsSource = data;
Serialize.Serialize(writer, data);
}
}
}
catch (Exception ex)
{ }
}
Hope this is helpful to you.
I want to add Search to Bing Map Control in my Windows Phone app. I did not find any references on the internet
Scenario
1. When the user enters the name of the place. The List Box will open to show the suggested places
2. The User will select the a single option and the coordinates of the location or pushpin will be displayed to that particular area.
Help me Out Please
It's fairly easy to accomplish. You need an AutoSuggestBox:
<AutoSuggestBox TextChanged="AutoSuggestBox_TextChanged" SuggestionChosen="AutoSuggestBox_SuggestionChosen">
<AutoSuggestBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Address.PostCode}" />
<TextBlock Text="," />
<TextBlock Text="{Binding Path=Address.Town}" />
</StackPanel>
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>
And when the text changes you issue a query. Since a server request takes some time, make sure that you choose a reasonable response interval. So DO NOT issue a query if the input has just changed for one char.
private async void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
if (sender.Text.Length > 3)
{
// Build a hint point
Geopoint hintPoint = [..]; // Up to you, should reflect the current location
await this.Progressbar.ShowAsync();
sender.ItemsSource = await getMapSuggestionsAsync(sender.Text, hintPoint);
await this.Progressbar.HideAsync();
}
else {
sender.ItemsSource = new List<MapLocation> { };
}
}
}
All you need now is a method that issues your query:
public static async Task<List<MapLocation>> getMapSuggestionsAsync(String query, Geopoint hintPoint)
{
List<MapLocation> locations = new List<MapLocation>();
// Find a corresponding location
MapLocationFinderResult result = await MapLocationFinder.FindLocationsAsync(query, hintPoint, 2);
// If the query provides results, try to get the respective city name and
// a zip code or deny first.
if (result.Status != MapLocationFinderStatus.Success)
return locations;
foreach (var location in result.Locations)
{
MapLocation ml = await resolveLocationForGeopoint(location.Point);
if (ml != null)
locations.Add(ml);
}
return locations;
}
public static async Task<MapLocation> resolveLocationForGeopoint(Geopoint geopoint)
{
MapLocationFinderResult result = await MapLocationFinder.FindLocationsAtAsync(geopoint);
if (result.Status == MapLocationFinderStatus.Success)
{
if (result.Locations.Count != 0)
// Check if the result is really valid
if (result.Locations[0].Address.Town != "")
return result.Locations[0];
}
return null;
}
The rest is simple: If the user chooses a suggestion you get the coordinates out of the MapLocation and show a pushpin on your map.
This is some code I wrote to get a Zip code and the city name. But you can really change it to search for anything else..
Results template in autosuggestbox are not showing and I don't know why. I'm using MVVM Light in the app. Let's go with the code :)
In the page:
<AutoSuggestBox x:Name="txtBusqueda" x:Uid="txtBusqueda"
ItemsSource="{Binding Lugares}"
Grid.Row="1" Margin="24 24 24 12"
MaxSuggestionListHeight="4" AutoMaximizeSuggestionArea="True"
TextMemberPath="Nombre"
>
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="TextChanged">
<core:InvokeCommandAction Command="{Binding ChangeTextCommand}" CommandParameter="{Binding Text, ElementName=txtBusqueda}" />
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
<AutoSuggestBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nombre}" TextWrapping="Wrap" />
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>
In the VM:
private List<LugarInfo> lugares;
public List<LugarInfo> Lugares
{
get { return this.lugares; }
set
{
if (this.lugares == value) return;
this.lugares = value;
RaisePropertyChanged(() => Lugares);
}
}
public RelayCommand<string> ChangeTextCommand { get; set; }
this.ChangeTextCommand = new RelayCommand<string>(async (s) =>
{
var result = await Api.GetInfoLugares(texto);
List<LugarInfo> lugares = new List<LugarInfo>();
foreach (var lugar in result)
{
lugares.Add(new LugarInfo()
{
Id = int.Parse(lugar.Id),
Tipo = lugar.Tipo,
Nombre = lugar.Nombre
});
}
this.Lugares = lugares;
});
So, as you can see, not too much trouble.
The results are returned and assigned to the property:
The problem is results are not displayed in control as you can see in the image.
Help will be appreciated.
your Lugares property will never raise RaisePropertyChanged because in your code you are adding your objects in lugares and than assigning it to This.Lugares which in setter is same so it will not raise the property change and and UI is not updated. change your code to as follows.
var myLugares = new List<LugarInfo>();
foreach (var lugar in result)
{
myLugares.Add(new LugarInfo()
{
Id = int.Parse(lugar.Id),
Tipo = lugar.Tipo,
Nombre = lugar.Nombre
});
}
this.Lugares = myLugares;
In test.xaml
<rlb:ReorderListBox
x:Name="reorderListBox"
Grid.Row="2"
Margin="12,0,12,12"
IsReorderEnabled="True"
ItemsSource="{Binding}" >
<rlb:ReorderListBox.ItemTemplate>
<DataTemplate>
<TextBlock
Margin="12,4,12,4"
FontSize="36"
Text="{Binding Name}" />
</DataTemplate>
</rlb:ReorderListBox.ItemTemplate>
</rlb:ReorderListBox>
int Test.xaml.cs
public void loadSource()
{
try
{
var xElem = XElement.Load("Data/SourcePage.xml");
var SourceNews =
from elem in xElem.Descendants("SourceNews")
select new ProNewsApp.Object.ObjectSource
{
Name = elem.Attribute("PageName").Value
};
reorderListBox.DataContext = SourceNews.ToList();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I'm follow here http://reorderlistbox.codeplex.com/ and my problem is when i'm drag and drop and my app was closed ?Why it's closed when I drag item ?How do i fix it
You need to use an ObservableCollection as the source of ReorderListBox. As the ReorderListbox changes indexes when items are reordered in the Model. So, try using:
System.Collections.ObjectModel.ObservableCollection<YourPublicClass> _observableList;
_observableList = new System.Collections.ObjectModel.ObservableCollection<YourPublicClass>(SourceNews.ToList());
reorderListBox.DataContext = _observableList;
And after rearranging items you can see that they are also changed in "_observableList".