I have a login screen that I want a activitymonitor to show up when I click the button. But I click the button and it doesn't show not real sure why.
Here is C#
On button click
activityIndicator.IsVisible = true;
WebApiService ws = new WebApiService();
var response = await ws.LoginAsync(Username.Text, Password.Text, UUID);
activityIndicator.IsVisible = false;
if (response.ResultCode == AuthenticationResultCodeEnum.SUCCESS)
{
// do something with the result
}
}
Here is my Xaml
<StackLayout >
<Label x:Name="Version" HeightRequest="50" VerticalTextAlignment="Start" HorizontalTextAlignment="End" Margin="0,30,20,0">
<Label.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="2" />
</Label.GestureRecognizers>
</Label>
<Image Source="LEDShield_Small.png" Margin="0,0,0,30"></Image>
<StackLayout Padding="20,0,20,0">
<Label Text="MI DNR Username" FontAttributes="Bold"></Label>
<Entry x:Name="Username" Placeholder="Username" IsSpellCheckEnabled="False" IsTextPredictionEnabled="False"></Entry>
<Label Text="MI DNR Password" FontAttributes="Bold"></Label>
<Entry x:Name="Password" Placeholder="Password" IsPassword="True"></Entry>
<Button x:Name="SigninButton" Text="Sign In" IsEnabled="False" HeightRequest="50"></Button>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*" />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="1" Orientation="Horizontal" HorizontalOptions="End">
<Label x:Name="RememberMeLabel" HeightRequest="10" Margin="0" VerticalTextAlignment="Center" Text="Keep Me Signed In">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding RememberMeLabelCommand}" />
</Label.GestureRecognizers>
</Label>
<CheckBox HeightRequest="50" VerticalOptions="Center" x:Name="RememberMe" IsChecked="{Binding IsRememberMeChecked}" Color="Green"></CheckBox>
</StackLayout>
<Label Grid.Row="0" Grid.Column="0" Margin="25" Text="Forgot Password" HorizontalOptions="Center" TextDecorations="Underline" >
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" NumberOfTapsRequired="1" />
</Label.GestureRecognizers>
</Label>
</Grid>
</StackLayout>
<Button x:Name="ResetRequestButton" IsVisible="false" Text="This account has been locked. Click here to to send a password reset request."></Button>
<ActivityIndicator IsRunning="true" x:Name="activityIndicator" Color="Green" VerticalOptions="Center" />
</StackLayout>
I use this class for ActivityIndicator:
public class ProgressSplash : Grid, IDisposable
{
public static ProgressSplash Show(Layout<View> parent)
{
return new ProgressSplash(parent);
}
ActivityIndicator ai;
Layout<View> parent;
private ProgressSplash(Layout<View> parent)
{
this.parent = parent;
HorizontalOptions = LayoutOptions.Fill;
VerticalOptions = LayoutOptions.Fill;
BackgroundColor = Color.FromHex("#40000000");
ai = new ActivityIndicator();
ai.HorizontalOptions = Device.RuntimePlatform == Device.UWP ? LayoutOptions.Fill : LayoutOptions.CenterAndExpand;
ai.VerticalOptions = LayoutOptions.CenterAndExpand;
ai.Opacity = 1;
if (parent is Grid)
{
if (((Grid)parent).RowDefinitions.Count > 1)
Grid.SetRowSpan(this, ((Grid)parent).RowDefinitions.Count);
if (((Grid)parent).ColumnDefinitions.Count > 1)
Grid.SetColumnSpan(this, ((Grid)parent).ColumnDefinitions.Count);
}
parent.Children.Add(this);
Children.Add(ai);
ai.IsVisible = true;
ai.IsRunning = true;
}
public void Dispose()
{
ai.IsRunning = false;
ai.IsVisible = false;
if (parent.Children.Contains(this))
parent.Children.Remove(this);
}
}
And there is how to use it:
using (var prc = ProgressSplash.Show(grdMain))
{
// ... do something slow
}
Where "grdMain" is main container on the page, which is Grid (it works with it only).
I'm not sure where ActivityIndicator tries to show, when inside a StackLayout.
Consider using it this way:
<Grid ...>
<StackLayout ...>
...
</StackLayout ...>
<ActivityIndicator x:Name="activityIndicator" IsRunning="False"
...
VerticalOptions="Center" />
</Grid>
In button click:
activityIndicator.IsRunning = true;
EXPLANATION:
The layout is a single-cell grid, with two children laid on top of each other.
First child is your "normal" content, inside a StackLayout.
Second child is ActivityIndicator, initially not running (so not visible).
When you set IsRunning to true, it shows up.
TECH NOTE: The reason to do this with IsRunning instead of IsVisible, is to avoid forcing page to perform a layout. OTOH, I've often done it (and seen it done by others), with code that toggles BOTH IsVisible and IsRunning. So maybe performance is a non-issue.
Regardless, by default it starts IsVisible=true, IsRunning=false, so might as well just toggle IsRunning.
Related
I have tried everything I could find on the internet and still cannot get the event to fire. My page contains 2 buttons as you can see which fire in the Simulator but not on my iphone. I have tried many different solutions found on the internet and the one I am showing here is the last one I attempted.
Here is the buttons defined in my view:
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=UpdateMileage}" CommandParameter="{Binding .}" IsEnabled="True" Text="Update" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="1" TextColor="Black" Margin="4"/>
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=Cancel}" CommandParameter="{Binding .}" Text="Cancel" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" TextColor="Black" Margin="4"/>
The viewModel code is as follows;
public ICommand UpdateMileage
{
get; set;
}
public EditViewModel()
{
UpdateMileage = new Command(UpdateMileageData);
MileageTableDefination mileage = new MileageTableDefination();
mileage = Application.Current.Properties["MileageData"] as MileageTableDefination;
SDate = Convert.ToDateTime(mileage.Date);
EntMiles = mileage.Miles.ToString();
EntGas = mileage.Gas.ToString();
EntCost = mileage.Price.ToString();
if (mileage.Note != null)
EntNote = mileage.Note.ToString();
EntId = mileage.Id;
}
public async void UpdateMileageData()
{
Analytics.TrackEvent("In UpdateMileageData Top ");
int autoId = Convert.ToInt32(Application.Current.Properties["autoId"]);
//Analytics.TrackEvent("Mileage Data in Enter Mileage: AutoId " + autoId);
error = false;
IsVisibleLabel = false;
if (EntMiles == "0" || EntMiles == null)
{
error = true;
IsVisibleLabel = true;
EntError = "Miles Driven Must Be Numeric";
}
else if (!System.Text.RegularExpressions.Regex.IsMatch(EntMiles, #"^[0-9]\d*(\.\d+)?$"))
{
error = true;
IsVisibleLabel = true;
EntError = "Miles Driven Must Be Numeric";
}
else if (Convert.ToDecimal(EntMiles) > 1000)
{
error = true;
//IsVisibleLabel = true;
EntError = "Miles Driven Since Last Fillup";
}
if (EntGas == "0" || EntGas == null)
{
error = true;
IsVisibleLabel = true;
EntError = "Gas Used Must Be Numeric";
}
else if (!System.Text.RegularExpressions.Regex.IsMatch(EntGas, #"^[0-9]\d*(\.\d+)?$"))
{
error = true;
IsVisibleLabel = true;
EntError = "Gas Used Must Be Numeric";
}
if (EntCost == "0" || EntCost == null)
{
error = true;
IsVisibleLabel = true;
EntError = "Cost Must Be Numeric";
}
else if (!System.Text.RegularExpressions.Regex.IsMatch(EntCost, #"^[0-9]\d*(\.\d+)?$"))
{
error = true;
IsVisibleLabel = true;
EntError = "Cost Must Be Numeric";
}
else if (Convert.ToDecimal(EntCost) > 300.00m)
{
error = true;
IsVisibleLabel = true;
EntError = "Cost Must Be Numeric And < $300";
}
Analytics.TrackEvent("In UpdateMileageData After If's Error = " + error);
if (!error)
{
miles.Date = SDate.Date;
miles.StrDate = SDate.Date.ToString("MM/dd/yyyy");
miles.Miles = Convert.ToDecimal(EntMiles);
miles.Gas = Convert.ToDecimal(EntGas);
miles.Id = EntId;
miles.CarId = autoId;
miles.MPG = Math.Round(Convert.ToDecimal(EntMiles) / Convert.ToDecimal(EntGas), 3);
miles.Price = Convert.ToDecimal(EntCost);
miles.Note = EntNote;
MileageItemRepository mir = new MileageItemRepository();
var results = await mir.UpdateMileageAsync(miles);
Analytics.TrackEvent("In UpdateMileageData Results = " + results);
if (results == 1)
{
Application.Current.Properties["UpdatedData"] = miles;
var nav = MyNavigation.GetNavigation();
await nav.PushAsync(new ViewMileage());
}
}
}
As you can see from my code I have logging statements and they are never reached. Any help would be much appreciated. Thanks in advance!
EDIT:
Here is the full xaml that contains the buttons
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:Validate="clr-namespace:MileageManagerForms.Validators"
xmlns:ViewModel ="clr-namespace:MileageManagerForms.ViewModels"
x:Class="MileageManagerForms.Views.EditMileage">
<ContentPage.BindingContext>
<ViewModel:EditViewModel/>
</ContentPage.BindingContext>
<Grid BackgroundColor="Purple">
<Grid.RowDefinitions>
<RowDefinition Height="47"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
<RowDefinition Height="30"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="85"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="85"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Frame BackgroundColor="#2196F3" Padding="10" CornerRadius="0" Grid.ColumnSpan="7" Grid.Row="0">
<Label Text="Edit Mileage" HorizontalTextAlignment="Center" TextColor="White" FontSize="25" />
</Frame>
<DatePicker x:Name="sDate" Format="MM/dd/yyyy" Date="{Binding SDate}" BackgroundColor="Gray" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" TextColor="White"/>
<Label Text="{Binding EntError}" FontAttributes="Bold" TextColor="Yellow" FontSize="Small" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="6" />
<Label Text="Miles:" TextColor="White" FontSize="Small" Grid.Row="3" Grid.Column="0" Margin="9" />
<Entry Text="{Binding EntMiles}" Keyboard="Numeric" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="3" Grid.Column="1" Margin="8" >
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="6"/>
<Validate:DecimalValidator />
</Entry.Behaviors>
</Entry>
<Label Text="Gas:" TextColor="White" FontSize="Small" Grid.Row="4" Grid.Column="0" Margin="12" Grid.ColumnSpan="2"/>
<Entry Text="{Binding EntGas}" Keyboard="Numeric" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="4" Grid.Column="1" Margin="8" >
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="6"/>
<Validate:DecimalValidator />
</Entry.Behaviors>
</Entry>
<Label Text="Cost:" TextColor="White" FontSize="Small" Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="3" Margin="9"/>
<Entry Text="{Binding EntCost}" Keyboard="Numeric" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Margin="8" >
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="7"/>
<Validate:DecimalValidator />
</Entry.Behaviors>
</Entry>
<Label Text="Note:" TextColor="White" FontSize="Small" Grid.Row="4" Grid.Column="2" Margin="10" Grid.ColumnSpan="2" HorizontalTextAlignment="Start"/>
<Entry Text="{Binding EntNote}" Keyboard="Default" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="4" Margin="8">
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="20"/>
</Entry.Behaviors>
</Entry>
<Entry Text="{Binding EntId}" Grid.Row="4" Grid.Column="8" Grid.ColumnSpan="2" Margin="8" IsVisible="false"/>
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=UpdateMileage}" CommandParameter="{Binding .}" IsEnabled="True" Text="Update" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="1" TextColor="Black" Margin="4"/>
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=Cancel}" CommandParameter="{Binding .}" Text="Cancel" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" TextColor="Black" Margin="4"/>
</Grid>
As for the question about the binding in the view code behind, I have this;
BindingContext = new EditViewModel();
I'm having an issue figuring out how to remove an item from my project while using the same button as I use to perform another task. To sum it up, I'm working on a project where I have a bunch of events a user can like/dislike. What I'm having issues with is trying to figure out how to remove the event from my project once the user has liked the event using the 'like' button. Essentially I want the 'like' button to perform 2 things, one being when its pressed setting it to "true" which is already doing that, but also I want it to remove the event from screen once it's liked.
Here is my XAML:
<StackLayout VerticalOptions="FillAndExpand">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image x:Name="LblEventImage"
Aspect="Fill"
HeightRequest="350" />
<BoxView BackgroundColor="Black"
HeightRequest="350"
Opacity="0.3" />
<Image Source="BackIconOrg.png"
Margin="5,40,0,0"
HorizontalOptions="Start"
VerticalOptions="Start"
Grid.Row="0">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="ImgBack" Tapped="backButton_Clicked"/>
</Image.GestureRecognizers>
</Image>
</Grid>
<Frame VerticalOptions="FillAndExpand"
IsClippedToBounds="False"
BackgroundColor="#263A4F"
Margin="0,-40,0,0"
CornerRadius="25"
HasShadow="False">
<StackLayout Margin="0,-50,0,0">
<Grid HeightRequest="200"
VerticalOptions="Start">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0"
Padding="5"
Spacing="5"
Margin="0,40,0,0">
<Label x:Name="LblEventName"
TextColor="#fc4600"
FontSize="Large"
FontFamily="TTBold"
FontAttributes="Bold"/>
<StackLayout Orientation="Horizontal"
Spacing="0">
<Frame BackgroundColor="#8B93A6"
BorderColor="#8B93A6"
Padding="8"
CornerRadius="15">
<Label TextColor="White"
x:Name="LblEventCategory"
FontFamily="TTNorms"/>
</Frame>
</StackLayout>
<StackLayout Orientation="Vertical" Grid.ColumnSpan="3">
<Label x:Name="LblEventCity"
TextColor="White"
FontFamily="TTNorms"/>
<Label x:Name="LblEventState"
TextColor="White"
FontFamily="TTNorms"/>
</StackLayout>
<!--<Label x:Name="LblLanguage"
TextColor="White" />
<Label x:Name="LblDuration"
TextColor="White" />-->
</StackLayout>
</Grid>
<Label Text="Details:"
FontSize="Medium"
Margin="0,20,0,0"
TextColor="White"
FontFamily="TTNorms"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.65*" />
<ColumnDefinition Width="0.35*" />
</Grid.ColumnDefinitions>
<Label Text="Scheduled Date:"
TextColor="White"
Grid.Row="0"
Grid.Column="0"
FontFamily="TTNorms"/>
<Label Text="August 20, 2021"
TextColor="#8B93A6"
Grid.Row="1"
Grid.Column="0"
FontFamily="TTNorms"/>
<Label Text="Group Size:"
TextColor="White"
Grid.Row="0"
Grid.Column="1"
FontFamily="TTNorms"/>
<Label x:Name="LblEventGroupSize"
TextColor="#8B93A6"
Grid.Row="1"
Grid.Column="1"
FontFamily="TTNorms"/>
<Label Text="Paid:"
TextColor="White"
Grid.Row="2"
Grid.Column="0"
FontFamily="TTNorms"/>
<Label x:Name="LblEventPay"
TextColor="#8B93A6"
Grid.Row="3"
Grid.Column="0"
FontFamily="TTNorms"/>
</Grid>
<BoxView BackgroundColor="#8B93A6"
HeightRequest="1" />
<Label Text="Description"
TextColor="White"
FontFamily="TTNorms"/>
<Label x:Name="LblEventDescription"
TextColor="#8B93A6"
FontFamily="TTNorms"/>
<StackLayout Orientation="Horizontal"
HorizontalOptions="Center"
VerticalOptions="Center"
Spacing="60"
Margin="0,30,0,0">
<Image Source="LikeButton.png"
HeightRequest="150">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="likedevent" Tapped="likeButton_Clicked" />
</Image.GestureRecognizers>
</Image>
<Image Source="DislikeButton.png"
HeightRequest="150">
<Image.GestureRecognizers>
<TapGestureRecognizer x:Name="dislikeevent" Tapped="dislikeevent_Tapped"/>
</Image.GestureRecognizers>
</Image>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</ContentPage.Content>
CS:
public partial class MatchDetail : ContentPage
{
private Event event1;
public MatchDetail(int eventId)
{
InitializeComponent();
GetEventDetail(eventId);
}
private async void GetEventDetail(int eventId)
{
event1 = await ApiService.GetEventById(eventId);
LblEventName.Text = event1.Name;
LblEventDescription.Text = event1.Description;
LblEventCity.Text = event1.City;
LblEventImage.Source = event1.FullImageUrl;
LblEventCategory.Text = event1.Category;
LblEventState.Text = event1.State;
LblEventGroupSize.Text = event1.GroupSize.ToString();
LblEventPay.Text = event1.PayTrueFalse;
}
private async void likeButton_Clicked(object sender, EventArgs e)
{
var likedEvent = new Result()
{
Name = LblEventName.Text,
UserId = Preferences.Get("userId", 0),
LikeTrueFalse = "True"
};
if (event1.LikeTrueFalse == "True")
{
//RemoveEvent
}
var response = await ApiService.LikedEvents(likedEvent);
if (response)
{
await DisplayAlert("", "Your event has been liked", "Ok");
}
else
{
await DisplayAlert("Oops", "something went wrong", "cancel");
}
}
private void backButton_Clicked(object sender, EventArgs e)
{
Navigation.PopModalAsync();
}
in your main page
MessagingCenter.Subscribe<object, int>(this, "RemoveEvent", (sender,id) =>
{
// do whatever to remove event "id" here
});
then in your detail page, after you have marked it as a favorite
Messaging.Center.Send<object, int>(this, "RemoveEvent", eventId);
I'm looking for the best way to change the content of a page, without navigating to a new one.
I tried having two stacklayouts, and on a button press I'd change the IsVisible and IsEnabled properties of each stack layout. Although this worked, I was left with a small white gap at the end of each layout (I believe this is a Xamarin.Forms bug).
What would be the best way to accomplish this task? Is there anything built into Xamarin.Forms that can do this that I have missed?
Here is a little sketch design for you to see what I mean:
Before suggesting I use tabs, I'll add that I already have tabs in the application, the sketch doesn't show that though. I need this navigation to work on only ONE page.
The code I used before, that didn't work is:
(Before anybody mentions the poor naming conventions and lack of content, I had to strip it all out as it's code written for an employer.
C#:
private void Button1_Clicked(object sender, EventArgs e)
{
Content2.IsVisible = false;
Content2.IsEnabled = false;
Content1.IsVisible = true;
Content1.IsEnabled = true;
}
private void Button2_Clicked(object sender, EventArgs e)
{
Content2.IsVisible = true;
Content2.IsEnabled = true;
Content1.IsEnabled = false;
Content1.IsVisible = false;
}
XML:
<ScrollView x:Name="content1" VerticalOptions="FillAndExpand" BackgroundColor="#f2f2f2">
<StackLayout Spacing="0">
<StackLayout Orientation="Horizontal" BackgroundColor="White" Padding="20,20,20,20" HorizontalOptions="FillAndExpand">
<StackLayout>
<Label Text="text:" FontFamily="{StaticResource BoldFont}"/>
<StackLayout Orientation="Horizontal">
<Image x:Name="content1image" HeightRequest="25" WidthRequest="25"/>
<Label x:Name="content1label" FontFamily="{StaticResource Font}" FontSize="27" TextColor="#969696"/>
</StackLayout>
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand">
<Entry x:Name="content1Entry" Keyboard="Numeric" Margin="0,25,0,0" Placeholder="0.00000000" FontFamily="{StaticResource Font}" FontSize="27" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="End" TextColor="#969696"/>
<Label x:Name="content1Label2" FontSize="14" FontFamily="{StaticResource Font}" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="End" TextColor="#969696"/>
</StackLayout>
</StackLayout>
<StackLayout Padding="20,30,20,0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Label Text="content1Label3" FontFamily="{StaticResource Font}"/>
<StackLayout Orientation="Horizontal">
<Button x:Name="content1button" Image="image.png" BackgroundColor="Transparent" HorizontalOptions="Start" Margin="0" WidthRequest="25" HeightRequest="25"/>
<Entry x:Name="content1Entry2" FontFamily="{StaticResource Font}" FontSize="12" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="End"/>
</StackLayout>
</StackLayout>
<StackLayout VerticalOptions="EndAndExpand" Padding="0,-1,0,0">
<Label x:Name="content1Label4" FontSize="19" HorizontalOptions="CenterAndExpand" FontFamily="{StaticResource Font}"/>
<Label x:Name="content1Label5" FontSize="12" TextColor="#b6b6b6" HorizontalOptions="CenterAndExpand" FontFamily="{StaticResource Font}"/>
<Button x:Name="content1Button2" VerticalOptions="End" HorizontalOptions="FillAndExpand" BorderRadius="25" BackgroundColor="#2r432d" BorderColor="#2r432d" TextColor="White" FontFamily="{StaticResource Font}" FontSize="20" BorderWidth="3" Margin="10,10,10,10"/>
</StackLayout>
</StackLayout>
I have not had very much success using Stacklayouts. Grids however has a lot of customizability and in my case it expands to fill all the area that you wish for.
This is how I would do it.
Xaml
<Grid x:Name="Grid1" IsVisible="False" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<Label FontSize="Medium" Text="Grid1 Label"/>
</Grid>
<Grid Grid.Row="1" HeightRequest="100" WidthRequest="375" VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand">
<Button x:Name="btnGrid1"/>
</Grid>
</Grid>
<Grid x:Name="Grid2" IsVisible="False" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<Label FontSize="Medium" Text="Grid2 Label"/>
</Grid>
<Grid Grid.Row="1" HeightRequest="100" WidthRequest="375" VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand">
<Button x:Name="btnGrid2"/>
</Grid>
</Grid>
Code-behind
private void Button1_Clicked(object sender, EventArgs e)
{
Grid2.IsVisible = false;
Grid1.IsVisible = true;
}
private void Button2_Clicked(object sender, EventArgs e)
{
Grid2.IsVisible = true;
Grid1.IsVisible = false;
}
I want to make BottomLeft, TopRight, TopLeft corner to rounded. I have tried with following. But, when text size is bit more, it doesn't show correct design.
I have added my code as following.
For better understanding, I have added image.
Render Code
public class ExtendedFrameRenderer : FrameRenderer
{
public override void Draw (CoreGraphics.CGRect rect)
{
base.Draw (rect);
var elem = (ExtendedFrame)this.Element;
UIRectCorner cornerstoRound = UIRectCorner.AllCorners;
if (elem != null)
{
cornerstoRound = UIRectCorner.BottomLeft | UIRectCorner.TopRight | UIRectCorner.TopLeft;
}
var path = UIBezierPath.FromRoundedRect(rect, cornerstoRound, new CoreGraphics.CGSize(8, 8));
var maskLayer = new CAShapeLayer();
maskLayer.Path = path.CGPath;
this.Layer.Mask = maskLayer;
}
}
View:
<Grid ColumnSpacing="2" Padding="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="15" />
</Grid.ColumnDefinitions>
<local:ExtendedFrame Grid.Column="1" OutlineColor="Transparent" HasShadow="False"
BackgroundColor="#30a5da">
<StackLayout Spacing="0">
<Label TextColor="White"
FontFamily="SourceSansPro-Regular"
FontSize="16"
Text="{Binding Text}" />
<Label Grid.Row="1" Grid.Column="1"
FontSize="12" HorizontalTextAlignment="End"
Text="{Binding MessageDateTime, StringFormat='{0:hh:mm tt}'}"
TextColor="White" />
</StackLayout>
</local:ExtendedFrame>
</Grid>
I think you can do it in XF without overriding FrameRenderer. This will give you shape what you want. And if you don't override renderer, it should better handle content inside
<Grid Margin="10" HorizontalOptions="EndAndExpand">
<Frame
BackgroundColor="Red"
CornerRadius="0"
HeightRequest="50"
HorizontalOptions="End"
VerticalOptions="End"
WidthRequest="20" />
<Frame
BackgroundColor="Blue"
CornerRadius="10"
HeightRequest="100">
<StackLayout>
<Label
FontSize="17"
Text="long fake text text"
TextColor="White" />
<Label
FontSize="12"
HorizontalTextAlignment="End"
Text="05:30 AM"
TextColor="Yellow" />
</StackLayout>
</Frame>
</Grid>
I think that is more simple. This is my plugin for UWP. Maybe it'll help you. look at the customRender.Link
I am currently working on a Xamarin CrossPlatform project and have implemented a Listview bound to an ObservableCollection. Everything works out fine until I remove an Item from the ListView. The images in the follow up items within the ListView disappear randomly - not all of them and a different amount of them every time. I guess it has something to do with the MemoryStream, but what do I have to change? Here´s the relevant part of my Model that is bound to the ListView:
public string ImageBase64
{
get
{
return imagebase64;
}
set
{
if (imagebase64 != value)
{
imagebase64 = value;
OnPropertyChanged(nameof(ImageBase64));
OnPropertyChanged(nameof(ImageSource));
}
}
}
public ImageSource ImageSource
{
get
{
if (!string.IsNullOrEmpty(imagebase64))
{
return ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(imagebase64)));
}
else
{
return null;
}
}
}
Here´s the relevant XAML:
<ListView x:Name="listView" Margin="20" ItemsSource="{Binding}" ItemSelected="OnListItemSelected" HasUnevenRows="True" SeparatorColor="{StaticResource primaryGreen}" SeparatorVisibility="Default">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Margin="0,5,0,5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="45" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Grid.RowSpan="3" Margin="-2,-2,-2,-2" Source="{Binding ImageSource}" HorizontalOptions="Start" VerticalOptions="Center" Aspect="AspectFill"/> <!-- This is the displayed Image -->
<Label Margin="10,0,0,0" Grid.Column="1" Grid.Row="0" FontAttributes="Bold" FontSize="18" TextColor="{StaticResource primaryGreen}" Text="{Binding VorNachname}" VerticalTextAlignment="Start" HorizontalTextAlignment="Start"/>
<Label Margin="10,0,0,0" Grid.Column="1" Grid.Row="1" Text="{Binding MediumSelected.Wert, StringFormat='via {0}'}" HorizontalOptions="FillAndExpand" VerticalTextAlignment="Start" HorizontalTextAlignment="Start"/>
<StackLayout Margin="10,0,0,0" Grid.Column="1" Grid.Row="2" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Alter,StringFormat='Alter: {0}'}" VerticalTextAlignment="Start" HorizontalTextAlignment="Start" HorizontalOptions="Start"/>
</StackLayout>
<StackLayout Margin="0,0,0,-5" Grid.Column="2" Grid.RowSpan="3" Orientation="Vertical" HorizontalOptions="End" VerticalOptions="End">
<Button WidthRequest="40" HeightRequest="40" BackgroundColor="White" BorderWidth="0" BorderColor="White" Image="socialmedia_18.png" Clicked="OnChangeClicked" CommandParameter ="{Binding}" VerticalOptions="EndAndExpand" />
<Button Margin="0,-15,0,0" WidthRequest="40" HeightRequest="40" BackgroundColor="White" BorderColor="White" Image="cancel_18.png" Clicked="OnDeleteClicked" CommandParameter ="{Binding}" VerticalOptions="End" />
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...and the Code behind:
async void OnDeleteClicked(object sender, EventArgs e)
{
Helper.TrackEvent("PeopleList_OnDeleteClicked");
//Get selected Person
Person person = (Person)((Button)sender).CommandParameter;
//Remove from Model
DBHelper.DBModel.People.Remove(person);
//Update database
App.Database.UpdateWithChildren(DBHelper.DBModel);
}
EDIT:
Resizing the images does not help, same problem. I tried it by binding a testvariable ImageSourceThumb to the ListViewItemImage:
public ImageSource ImageSourceThumb
{
get
{
if (!string.IsNullOrEmpty(imagebase64))
{
return ImageSource.FromStream(() => new MemoryStream(ImageResizer.ResizeImage(Convert.FromBase64String(imagebase64), 64, 64)));
}
else
{
return null;
}
}
}
I had a similar problem. When I loaded or updated my listview not all the images showed up.
I fixed my problem resizing the images. Huge images gived me a outofmemory exception. Resizing those images to a smaller resolution fixed these problems.