optional split string ascii char - xamarin.forms

Is there a ascii char (non printable) to suggest where to split a string when needed. This in order to show in a cell correctly, even when the screen is rotated. I use buttons in a 5x2 grid in this example.
So, "powerslave" change to "power slave" when the text is wrapped to fit into the cell incase the screen is vertical.
eg. "stalingrad" does not fit into a cell, so I would like the have
"staling grad" when the screen is vertical.
I want to use it for a xamarin android app. Now xamarin (4.8) makes
"stalingra d" or "powerslav e". I do not have any control because there is no wrapping feedback.

Yes,you can change the data source of above CollectionView based on the orientation of the device Orientation.
First,for how to detect the orientation of the device, you can override method OnSizeAllocated in your page.
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (Height > Width)
{
viewModel.LoadPortraitData();
}
else {
viewModel.LoadLandscapeData();
}
}
For more, check Device Orientation.
Second ,according to your need, we can use CollectionView to display the string list. And we can display its items in a vertical grid by setting its ItemsLayout property to VerticalGrid.
<CollectionView ItemsLayout="VerticalGrid, 2"
ItemsSource="{Binding items}">
I have made a simple demo,you can refer to the following code:
<StackLayout Margin="20">
<CollectionView ItemsLayout="VerticalGrid, 2"
ItemsSource="{Binding items}">
</CollectionView>
</StackLayout>
The code of VerticalGridTextPage.xaml.cs:
public partial class VerticalGridTextPage : ContentPage
{
MyViewModel viewModel;
public VerticalGridTextPage()
{
InitializeComponent();
viewModel = new MyViewModel();
this.BindingContext = viewModel;
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (Height > Width)
{
viewModel.LoadPortraitData();
}
else {
viewModel.LoadLandscapeData();
}
}
}
MyViewModel.cs
public class MyViewModel
{
public ObservableCollection<string> items { get; set; } = new ObservableCollection<string>();
public void LoadLandscapeData()
{
items.Clear();
items.Add("power slave");
items.Add("staling grad");
}
public void LoadPortraitData() {
items.Clear();
items.Add("powerslave");
items.Add("stalinggrad");
}
public MyViewModel() {
LoadPortraitData();
}
}
For more, check: Vertical grid.

I think the only character that can wrap text in xamarin forms is the 0x20 space char.
So, I updated a TTF font. I 0x20 copied space to the underscore and modified the space char 0x20 to 0 horizontal width.
How to use custom forts I found here (by Gerald Versluis).
Now I can parse any text. Replace any " " with "_ ", and whenever a wrap is allowed I can use a " ".
<Button Grid.Row="0" Grid.Column="0" Text="Aces_ High" />
<Button Grid.Row="0" Grid.Column="1" Text="Agents_ of_ Steel" />
<Button Grid.Row="1" Grid.Column="0" Text="Break ing_ the_ Law" />
<Button Grid.Row="1" Grid.Column="1" Text="Fast_ as_ a_ Shark" />
<Button Grid.Row="2" Grid.Column="0" Text="fht_ Bells_ Tolls" />
<Button Grid.Row="2" Grid.Column="1" Text="Holy_ Diver" />
<Button Grid.Row="3" Grid.Column="0" Text="Mad_ House" />
<Button Grid.Row="3" Grid.Column="1" Text="Power slave" />
<Button Grid.Row="4" Grid.Column="0" Text="Symp_ of_ De struct ion" />
<Button Grid.Row="4" Grid.Column="1" Text="Stalin grad" />
<Button Grid.Row="5" Grid.Column="0" Text="t_ Number_ ot_ Beast" />
<Button Grid.Row="5" Grid.Column="1" Text="Stop" />
Then I get this result. Actually, I would expect this functionality would be in the xamarin platform.

Related

Observable collection is not triggering when changes the one object property in xamarin forms

I have a checkbox in my ListView. and the property "IsSelected" binded to the checkbox which is in the Assignment model.
The IsSelected property is triggering when I click on the checkbox. But "ObservableCollection ListActivities" is not triggering which is ViewModel when checkbox clicked.
How ObservableCollection ListActivities will trigger when clicks on the checkbox.
Please Help me.
Model:
public class Assignment : NotifyPropertyChanged
{
[JsonIgnore]
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set
{
_isSelected = value;
RaisePropertyChanged(nameof(IsSelected));
}
}
}
ViewModel:
private ObservableCollection<Assignment> _listActivities;
public ObservableCollection<Assignment> ListActivities
{
get => _listActivities;
set
{
RaiseAndSetIfChanged(ref _listActivities, value);
RaisePropertyChanged(nameof(ListActivities));
}
}
XAML:
<ListView x:Name="ClusteredActivities"
ItemsSource="{Binding ListActivities, Mode=TwoWay}"
Margin="20"
SeparatorVisibility="None"
HorizontalOptions="Center">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="0">
<CheckBox
HorizontalOptions="Start"
VerticalOptions="Center"
Color="Black"
IsChecked="{Binding IsSelected, Mode=TwoWay}">
</CheckBox>
<Label Style="{DynamicResource ItalicLabel}">
<Label.FormattedText>
<FormattedString>
<FormattedString.Spans>
<Span Text="{Binding ParentIncident.ErpSrNumber}" />
<Span Text=", " />
<Span Text="{Binding ActivityId}" />
<Span Text=", " />
<Span Text="{Binding ActivityType}"/>
</FormattedString.Spans>
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
From document ObservableCollection Class,we know that ObservableCollection<T> Class
Represents a dynamic data collection that provides notifications when
items get added or removed, or when the whole list is refreshed.
So, we can receive notification once items get added or removed, or when the whole list is refreshed. On the other side, changing one property in the item will not trigger notification for ListActivities .
How ObservableCollection ListActivities will trigger when clicks on
the checkbox.
If we want to trigger ListActivities ,we can add relative code in the setter method.
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set
{
_isSelected = value;
RaisePropertyChanged(nameof(IsSelected));
// add relative code here for `ListActivities`
}
}

Xamarin ViewCell subclass getting error in run time. "ViewCell Must Have a View"?

I am getting this runtime error saying that the CellView needs a View. I have not found anything on this so far, here on StackOverflow or on google, so I am in the total dark about what needs to be fixed.
I need to set up a list view with 2 sections. the first one is for the bikes that are in the database and the other section is for the ones that we detected but are not saved in the DB yet.
Both sections use the same UI (cell) and so I need to be able to have a sliding button (ContextAction MenuItem) in the first section and for the second section this action needs to be disabled/removed.
If it's not possible then I would need to have the action for the second section "Add" instead of "Forget".
This is why I created a subclass.
this is my code.
(edit: corections)
---- .xaml file ----
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="EGrid18.Components.BikeSelectionCell"
x:Name="ThisCell">
<ViewCell.View>
<StackLayout>
<Grid ColumnSpacing="10"
BindingContext="{x:Reference ThisCell}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="32"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding BikeName}"
StyleClass="bikecellname"
Grid.Row="0"
Grid.Column="0"
VerticalOptions="Center"
HorizontalOptions="StartAndExpand"/>
<Image Source="{Binding Image}"
HeightRequest="16"
WidthRequest="16"
VerticalOptions="Center"
Aspect="AspectFit"
Grid.Column="1"
Grid.Row="0"/>
<Label Text="{Binding Distence, StringFormat='{0:F2} M'}"
Grid.Row="0"
Grid.Column="2"
VerticalOptions="Center"/>
</Grid>
</StackLayout>
</ViewCell.View>
</ViewCell>
---- .cs file ----
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace EGrid18.Components
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BikeSelectionCell : ViewCell
{
public static BindableProperty BikeNameProperty =
BindableProperty.Create(nameof(BikeName), typeof(string), typeof(BikeSelectionCell), string.Empty);
public string BikeName
{
get => (string)GetValue(BikeNameProperty);
set => SetValue(BikeNameProperty, value);
}
public static BindableProperty ImageProperty =
BindableProperty.Create(nameof(Image), typeof(string), typeof(BikeSelectionCell), string.Empty);
public string Image
{
get => (string)GetValue(ImageProperty);
set => SetValue(ImageProperty, value);
}
public static BindableProperty DistenceProperty =
BindableProperty.Create(nameof(Distence), typeof(double), typeof(BikeSelectionCell), 0.0);
public double Distence
{
get => (double)GetValue(DistenceProperty);
set => SetValue(DistenceProperty, value);
}
public static readonly BindableProperty ForgetCommandProperty =
BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(BikeSelectionCell), null);
public ICommand ForgetCommand
{
get { return (ICommand)GetValue(ForgetCommandProperty); }
set { SetValue(ForgetCommandProperty, value); }
}
public Command OnForget => new Command(() => Execute(ForgetCommand));
// Helper method for invoking commands safely
public static void Execute(ICommand command)
{
if (command == null) return;
if (command.CanExecute(null))
{
command.Execute(null);
}
}
protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if(propertyName == nameof(Image))
{
this.ContextActions.Clear();
if (Image != "unknown")
{
this.ContextActions.Add(new MenuItem()
{
Text = "Forget",
Command = ForgetCommand,
CommandParameter = this
});
}
}
}
}
}
--- the .xaml file that consumes the CellView subclass ---
<?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:vm="clr-namespace:EGrid18.ViewModels"
xmlns:iOS="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
xmlns:components="clr-namespace:EGrid18.Components"
iOS:Page.UseSafeArea="True"
x:Class="EGrid18.Views.BikeSelectionPage"
Title="Bike Selection List">
<ContentPage.Resources>
<ResourceDictionary>
<vm:BikeListViewModel x:Key="vm"/>
<StyleSheet Source="/CSS/Styles.css"/>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="ScanButton" Text="Scan"
Command="{Binding Source={StaticResource vm}, Path=OnScanCommand}"
CommandParameter="{Binding Source={StaticResource vm}, Path=IsScanning}" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Margin="8,8,8,8">
<Label Text="Bike Selection Page"
StyleClass="titlelabel"/>
<ListView x:Name="ListView"
BindingContext="{StaticResource vm}"
StyleClass="listview"
ItemsSource="{Binding BikeList}"
IsGroupingEnabled="True"
SelectedItem="{Binding SelectedBike}"
Margin="8,8,8,8">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Heading}"
VerticalOptions="Center"
Margin="8,8,8,8"/>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<components:BikeSelectionCell
BikeName="{Binding Name}"
Image="{Binding Image}"
Distence="{Binding Distence}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
A ViewCell is not a View - it isn't part of View heirarchy. It is a "wrapper" that is needed by ListView, around each item.
Personally, I never create subclasses of ViewCell, though that can be done.
IMHO, Its more straightforward to make a custom View, then wrap that in <ViewCell> to use with ListView.
As a View, you can inherit from any view class. If you don't know what else to use, inherit from ContentView. (Or from StackLayout, if need to add multiple children views.) In your case, your View is a StackLayout.
public partial class BikeSelectionView : StackLayout
... // All the lines of code you have in BikeSelectionCell go here.
xaml:
<StackLayout ... x:Name="ThisCell">
<Grid ColumnSpacing="10" ...>
... All the remaining lines of code from your xaml ...
</StackLayout>
Usage inside ListView's ItemTemplate:
<DataTemplate>
<ViewCell>
<components:BikeSelectionView
BikeName="{Binding Name}"
Image="{Binding Image}"
Distence="{Binding Distence}"/>
</ViewCell>
</DataTemplate>
One advantage of this approach is if you switch from ListView to CollectionView (which does not use ViewCells), you can still use the custom class:
<CollectionView.ItemTemplate>
<DataTemplate>
<components:BikeSelectionView ... />
</DataTemplate>
</CollectionView.ItemTemplate>
The error was coming from a missing constructor that needed to initialize the Component.
public BikeSelectionCell()
{
InitializeComponent();
}
In the end I used the suggestion ToolmakerSteve. I also used a custom DataTemplateSelector to set specifics DataTemplate for the 2 different sections
I am setting this as the answer for any one looking for this problem as the problem was really the missing call to InitializeComponent();

Exrin MasterDetailPage

I'm using a MasterDetailPage in exrin
this is my ViewContainer
public class MainViewContainer : Exrin.Framework.ViewContainer, IMasterDetailContainer
{
private readonly MasterDetailPage r_MasterPage;
public MainViewContainer(MenuStack i_MenuStack, MainStack i_MainStack)
: base(eContainer.Main.ToString())
{
r_MasterPage = new MasterDetailPage();
MasterDetailProxy masterProxy = new MasterDetailProxy(r_MasterPage);
NativeView = masterProxy.View;
Proxy = masterProxy;
DetailStack = i_MainStack;
MasterStack = i_MenuStack;
RegionMapping.Add(eRegions.Menu, ContainerType.Master);
RegionMapping.Add(eRegions.Main, ContainerType.Detail);
}
public IHolder MasterStack { get; set; }
public IHolder DetailStack { get; set; }
public IMasterDetailProxy Proxy { get; set; }
public bool IsPresented
{
get
{
return r_MasterPage.IsPresented;
}
set
{
r_MasterPage.IsPresented = value;
}
}
public void SetStack(ContainerType i_ContainerType, object i_Page)
{
switch (i_ContainerType)
{
case ContainerType.Detail:
r_MasterPage.Detail = i_Page as Page;
break;
case ContainerType.Master:
r_MasterPage.Master = i_Page as Page;
break;
}
}
}
and this is my IMasterDetailProxy
public class MasterDetailProxy : IMasterDetailProxy
{
private readonly MasterDetailPage r_MasterPage;
public MasterDetailProxy(MasterDetailPage i_MasterPage)
{
View = i_MasterPage;
r_MasterPage = i_MasterPage;
}
public object DetailNativeView
{
get
{
return r_MasterPage.Detail;
}
set
{
r_MasterPage.Detail = value as Page;
}
}
public object MasterNativeView
{
get
{
return r_MasterPage.Master;
}
set
{
Page page = value as Page;
if(string.IsNullOrEmpty(page.Title))
{
page.Title = "Please set your MasterPage Title";
}
r_MasterPage.Master = page;
}
}
public object View { get; set; }
}
I'm using it show a menu on the master and the pages on the Detail part.
my menu view is
<base:PageProxy xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:base="clr-namespace:Exrin.Base;assembly=Exrin.Base"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns:control="clr-namespace:BeAttend.Control;assembly=BeAttend"
x:Class="BeAttend.View.MenuView" Title="Menu">
<base:PageProxy.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS" >Icon-Small.png</On>
</OnPlatform>
</base:PageProxy.Icon>
<ContentPage.Content>
<Grid BackgroundColor="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
<Image Source="menubg.jpg" Aspect="AspectFill" />
<StackLayout Padding="0,20,0,0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" >
<controls:CircleImage BorderColor="White" BorderThickness="2" Source="{Binding VisualState.User.Picture}" Aspect="AspectFit" WidthRequest="100" HeightRequest="100" />
<Label Text="{Binding VisualState.User.Name}" TextColor="White" FontSize="Large" />
</StackLayout>
</Grid>
<StackLayout Margin="20,20,20,0" Grid.Row="1" Spacing="15">
<control:NavigationItem Text="Dashboard" Icon="fa-archive" Command="{Binding NavigationCommand}" CommandParameter="Dashboard" />
<ContentView HeightRequest="1" BackgroundColor="Gray" />
<control:NavigationItem Text="Beacons" Icon="fa-archive" Command="{Binding NavigationCommand}" CommandParameter="Beacons" />
<ContentView HeightRequest="1" BackgroundColor="Gray" />
<control:NavigationItem Text="Create event" Icon="fa-archive" Command="{Binding NavigationCommand}" CommandParameter="CreateEvent" />
<ContentView HeightRequest="1" BackgroundColor="Gray" />
<control:NavigationItem Text="My events" Icon="fa-archive" Command="{Binding NavigationCommand}" CommandParameter="MyEvents" />
<ContentView HeightRequest="1" BackgroundColor="Gray" />
<control:NavigationItem Text="Registered events" Icon="fa-archive" Command="{Binding NavigationCommand}" CommandParameter="RegisteredEvents" />
<ContentView HeightRequest="1" BackgroundColor="Gray" />
<control:NavigationItem Text="Attendance QR" Icon="fa-archive" Command="{Binding NavigationCommand}" CommandParameter="AttendanceQr" />
<ContentView HeightRequest="1" BackgroundColor="Gray" />
<control:NavigationItem Text="Join Event" Icon="fa-archive" Command="{Binding NavigationCommand}" CommandParameter="JoinEvent" />
<ContentView HeightRequest="1" BackgroundColor="Gray" />
<control:NavigationItem Text="Logout" Icon="fa-arrow-circle-left" Command="{Binding LogoutCommand}" />
</StackLayout>
</Grid>
</ContentPage.Content>
</base:PageProxy>
I have a couple of problems:
1. on Android I have the hamburger menu button automatically but on iOS I don't have any icon, I tried to set an icon for the menu view for iOS using
<base:PageProxy.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS" >Icon-Small.png</On>
</OnPlatform>
</base:PageProxy.Icon>
on the menu view but it doesn't work.
2. On iOS the page title is "Please set your MasterPage Title" (The proxy sets it if the page title is empty) but you can see on the menu view that I set the title for the page, this happens only on iOS.
https://drive.google.com/file/d/0B3YFjr58f7_OMC04Y0FreVRvVlE/view?usp=sharing
when pressing a link on the menu I want the master page to disappear it currently stays on and hides part of the Detail page until I press on the Detail page.
On the Detail page I have a back button, so if I want to navigate to another page I have to first press back and then I can see the the menu icon to show the mater page and select another link. How can I replace the back button to always show the hamburger menu button?
this is my stack
public class MainStack : BaseStack
{
public MainStack(IViewService i_ViewService)
: base(new NavigationProxy(new NavigationPage()), i_ViewService, eStack.Main, nameof(Views.eMain.Dashboard))
{
ShowNavigationBar = true;
}
protected override void Map()
{
NavigationMap<DashboardView, DashboardViewModel>(nameof(Views.eMain.Dashboard));
NavigationMap<BeaconsView, BeaconsViewModel>(nameof(Views.eMain.Beacons));
NavigationMap<BeaconAddView, BeaconAddViewModel>(nameof(Views.eMain.AddBeacon));
NavigationMap<BeaconEditView, BeaconEditViewModel>(nameof(Views.eMain.EditBeacon));
NavigationMap<EventCreateView, EventCreateViewModel>(nameof(Views.eMain.CreateEvent));
NavigationMap<EventsCreatedView, EventsCreatedViewModel>(nameof(Views.eMain.MyEvents));
NavigationMap<EventsRegisteredView, EventsRegisteredViewModel>(nameof(Views.eMain.RegisteredEvents));
NavigationMap<EventEditView, EventEditViewModel>(nameof(Views.eMain.EditEvent));
NavigationMap<EventView, EventViewModel>(nameof(Views.eMain.ViewEvent));
NavigationMap<AttendanceQrView, AttendanceQrViewModel>(nameof(Views.eMain.AttendanceQr));
NavigationMap<JoinEventView, JoinEventViewModel>(nameof(Views.eMain.JoinEvent));
}
}
If you want to remove the Master page when you click a link, you will find that in your IMasterDetailContainer, there is a property called IsPresented. Set this to true or false, to manually show or hide the page.
If you set the Title of your ContentPages, this will replace any default title being set.
Ensure the Icon is in your Resources folder. Also if it's still not shown in iOS, set the icon to the Detail, Navigation or ContentPage. I can't remember which one you are meant to set it to. But if you try that, you can find out which one works.

How can I remove Margin from a Button in Xamarin Forms XAML?

I'm totally new to Xamarin, so please be patient!
Somehow Xamarin adds a mysterious Margin to all my Buttons and I don't know how to get rid of it.
Here is my Code:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="RockStamp.CameraSearch_Scan">
<StackLayout Orientation="Vertical" Padding="0" Spacing="0">
<StackLayout Orientation="Horizontal" Padding="0" Spacing="0">
<Button Text="Test" HeightRequest="50" WidthRequest="60" TextColor="#333333" x:Name="btnBack" VerticalOptions="Center" HorizontalOptions="Start" ></Button>
<Label Text="Scan a..." FontSize="20" FontAttributes="Bold" BackgroundColor="{StaticResource BlueBackColor}" TextColor="White" VerticalOptions="Start" HorizontalOptions="FillAndExpand" />
</StackLayout>
<Label Text="Steady now, we try to detect your..." FontSize="16" VerticalOptions="Start" HorizontalOptions="Start" />
<!-- Camera Placeholder -->
<BoxView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="#eeeeee" ></BoxView>
<StackLayout Orientation="Horizontal" Padding="0" Spacing="0">
<Button Text="Cancel" TextColor="#333333" x:Name="btnCancel" VerticalOptions="Center" HorizontalOptions="FillAndExpand" ></Button>
<Button Text="Scan now!" TextColor="#333333" x:Name="btnScan" VerticalOptions="Center" HorizontalOptions="FillAndExpand" ></Button>
</StackLayout>
</StackLayout >
</ContentPage>
Here an image:
You can clearly see the space around the Button. Where does it come from - and more important: How can I remove it?
The problem is that the default button background contains this margin. You have to set the BackgroundColor to a color and set the BorderWidth and BorderRadius to zero manually.
<Button
BackgroundColor="Fuchsia"
BorderRadius="0"
BorderWidth="0"
Text="Test"
HeightRequest="50"
WidthRequest="60"
TextColor="#333333"
x:Name="btnBack"
Margin="0"
VerticalOptions="Start"
HorizontalOptions="Start" />
You may have fixed the problem :
The way I fixed this is to create a renderer on android to override the button on xamarin.
public class FixedMarginRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control != null)
{
// remove default background image
Control.Background = null;
Control.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "BackgroundColor")
{
// You have to set background color here again, because the background color can be changed later.
Control.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
}
}
}
Just to add on to Sven-Michael Stübe's answer.
If none of your buttons require the Margin then create a Style or a custom control in your PCL (eg: MarginLessButton).
Setting BackgroundColor, BorderWidth, and BorderRadius manually does not work anymore. But you can use platform configuration to remove the padding. It is also necessary to remove the shadow otherwise there will be some vertical margin.
Try something like this:
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
namespace MyControls
{
public class ButtonNoMargin : Xamarin.Forms.Button
{
public ButtonNoMargin() : base()
{
this.On<Android>().SetUseDefaultPadding(false);
this.On<Android>().SetUseDefaultShadow(false);
}
}
}
For more information, see https://github.com/xamarin/Xamarin.Forms/pull/1935

How do I set the size of an image within a ListView?

How do I set the size of an image within a ListView?
The targeted device is Windows Phone 10 (i.e. Windows Universal Platform).
I've discovered the following documentation:
Note that when targeting Windows Phone 8.1, ImageCell will not scale
images by default. Also, note that Windows Phone 8.1 is the only
platform on which detail text is presented in the same color and font
as primary text by default. Windows Phone 8.0 renders ImageCell as
seen below:
I've tried:
<ListView Grid.Row="1" ItemsSource="{Binding Photos}" SelectedItem="{Binding SelectedPhoto, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell ImageSource="{Binding ImageSource}" Text="{Binding Description}" TextColor="Silver" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The above image shows a full-blown image without confining the size of the image to fit as a listview item.
I've also tried:
<ListView Grid.Row="1" ItemsSource="{Binding Photos}" SelectedItem="{Binding SelectedPhoto, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding ImageSource}" Aspect="AspectFit" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The above code doesn't show any image. It just shows a white background.
Few things:-
ImageCell has no ability to specify the image width / height (v2.0.x).
Your second example is more on track, however, you need to wrap it in a ViewCell as you are dealing with a ListView like so:-
<ListView ItemsSource="{Binding Photos}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Image Source="{Binding MyImage}" Aspect="AspectFit" WidthRequest="{Binding MyWidth}" HeightRequest="{Binding MyHeight}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Also, note that the default for a ListView is set to have equal row heights.
Therefore if you have different image sizes, chances are this may not produce the output you want.
To get around this, specify HasUnevenRows='True'.
If you further do BindableProperties for what you want the ImageWidth and ImageHeight in your ViewModel, and specify them as in the example above using WidthRequest and HeightRequest for Image you will get something like this for the output when specifying different values:-
Just adding salt to a cooked meal, You can also do it dynamically:
<Slider x:Name="slider" Maximum="600" Minimum="30" />
<ListView RowHeight="55" x:Name="lv_prayers_categories_page"
ItemsSource="{Binding SimpleList}"
HasUnevenRows="true"
BackgroundColor="Transparent"
SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#eee" HeightRequest="50" >
<StackLayout Orientation="Horizontal">
<Image Aspect="AspectFill" Source="{Binding Image}" HeightRequest="{Binding Source={x:Reference slider}, Path=Value}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
<Label Text="{Binding Name}"
TextColor="#f35e20" />
<Label Text="{Binding ID}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
View Modal:
private ObservableCollection<SimpleImage> _impleList;
public ObservableCollection<SimpleImage> SimpleList
{
get => _impleList;
set => SetProperty(ref _impleList, value);
}
SimpleList = new ObservableCollection<SimpleImage>()
{
new SimpleImage(){
ID = 0,
Name = "Female",
Image = "https://griffonagedotcom.files.wordpress.com/2016/07/profile-modern-2e.jpg"
},
new SimpleImage(){
ID = 1,
Name = "Male",
Image = "https://media.istockphoto.com/photos/profile-view-of-confident-sportsman-picture-id488758510?k=6&m=488758510&s=612x612&w=0&h=yIwLu2wdd2vo317STdyNlKYIVIEJEFfDKfkY8pBIfaA="
},
new SimpleImage(){
ID = 2,
Name = "Android",
Image = "https://www.cnn.co.jp/storage/2015/11/06/17626d508c2c2a8c8c322d353631a431/zuckerberg-getty.jpg"
},
};
Modal:
public class SimpleImage : BindableBase
{
private int _id;
public int ID
{
get { return _id; }
set { SetProperty(ref _id, value); }
}
private string _name;
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
private ImageSource _image;
public ImageSource Image
{
get { return _image; }
set { SetProperty(ref _image, value); }
}
}

Resources