Xamarin's Buttons issue - xaml

I've only recently started Xamarin and I'm having trouble figuring out how to design a few blocks. I'm trying to create some simple buttons to navigate with and it was decent (picture 2). But as soon as I tried binding it to a data, the design basically ran off (picture 1). Any suggestions?
Image of the problem
Image of the attempt
Below are the codes for picture 1:
<ListView x:Name="displayCourses" ItemsSource="{Binding CourseName}">
<ListView.Header>
<Grid HorizontalOptions="Center">
<!--<Button Text="{Binding CourseName}" BackgroundColor="#ea3e15"
CornerRadius="20" WidthRequest="290" HeightRequest="130"
FontAttributes="Bold" FontSize="26" Clicked="NextPage"
/>-->
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Button Text="{Binding CourseName}" BackgroundColor="#ea3e15" TextColor="#fff"
CornerRadius="20"
FontAttributes="Bold" FontSize="26"
/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
CS codes linking the data together
protected async override void OnAppearing()
{
base.OnAppearing();
displayCourses.ItemsSource = await firebaseHelper.GetCourses();
}
public async Task<List<Course>> GetCourses()
{
FirebaseClient firebase = new FirebaseClient("https://pra-ece32-default-rtdb.firebaseio.com/");
return (await firebase
.Child("Courses")
.OnceAsync<Course>()).Select(item => new Course
{
CourseName = item.Object.CourseName,
CourseID = item.Object.CourseID,
ExamDate = item.Object.ExamDate,
}).ToList();
}

The width of a row inside the listview will always take up the entire width of the listview itself. There is no way to have extra space between the end of a Row and the edge of the listview, nor would that make any sense.
But you can use Grid to meet your requirement. Please set ListView HasUnevenRow="True" to automatically size row height to fit content.
<ListView
x:Name="displayCourses"
HasUnevenRows="True"
ItemsSource="{Binding courses}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="1"
Margin="20"
BackgroundColor="#ea3e15"
CornerRadius="20"
FontAttributes="Bold"
FontSize="26"
HeightRequest="50"
Text="{Binding coursename}"
TextColor="#fff"
WidthRequest="200" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Related

Label TextColor Binding in DataTamplate xaml Xamarin

I do have a CollectionView with a binding for the text in the labels. This works without a problem.
But now I want to add a binding for the Text Color and I don't know how to do it.
my xaml:
<CollectionView ItemsSource="{Binding List}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<ScrollView>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Text="{Binding AttributFromListObject}" TextColor="{Binding TextColor}" Grid.Row="0" Grid.Column="0"/>
<
</Grid>
</ScrollView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
I have set the bindingcontext in the codebehind.
In a normal label without the DataTemplate, the binding TextColor is working.
How can I tell the xaml that it should use the bindingcontext of the page for the TextColor?
Thanks for your help!
#Json comment had the answer.
Needed to add the following
xmlns:ViewModels="clr-namespace:AppName.ViewModels"
TextColor="{Binding Source={RelativeSource AncestorType={x:Type ViewModels:MyViewModel}}, Path=TextColor}"

Xamarin forms, find corresponding checkbox to label in listview and check it when clicked on label

I have this ListView:
<ListView x:Name="listview_items"
Margin="0,10,0,0"
VerticalScrollBarVisibility="Always"
HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="5"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding itemText}"
FontSize="22"
Margin="0,5,0,5"
FontFamily="Font_11"
TextColor="#424242">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Label.GestureRecognizers>
</Label>
<CheckBox
Color="#97A5AD"
IsChecked="{Binding isChecked}"
CheckedChanged="chk_accept_shipment_CheckedChanged"
Grid.Column="1"
Scale="1"
HorizontalOptions="End"
Margin="0,0,0,0"
x:Uid="{Binding itemID}"
x:Name="{Binding itemID}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As you can see, it contains a Label and a CheckBox, when the user checks the checkbox, I gets checked. But now, I have a gesture recognizer attached to the label. When the user taps the label, I want to find out which checkbox is next to the label and also check it (as if the user actually clicked the checkbox).
How do I find the corresponding checkbox to the label next to it?
I would personally bind the IsChecked property to my ViewModel.
Example:
<StackLayout
HorizontalOptions="Start"
Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding SelectAllCategoriesCommand}" NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>
<CheckBox IsChecked="{Binding IsAllCategoriesSelected}" />
<Label Text="Select All Categories" />
</StackLayout>
The binded property can be something like :
private bool _isAllCategoriesSelected;
public bool IsAllCategoriesSelected
{
get => _isAllCategoriesSelected;
set
{
_isAllCategoriesSelected = value;
RaisePropertyChanged(() => IsAllCategoriesSelected);
}
}
First you have to pass CommandParameter in tap so you can get that in TapGestureRecognizer_Tapped In that you will get which Item table click so according that you have to check check box
<Label.GestureRecognizers>
<TapGestureRecognizer CommandParameter="{Binding itemID}" Tapped="TapGestureRecognizer_Tapped"/>
</Label.GestureRecognizers>
async void TapGestureRecognizer_Tapped(System.Object sender, System.EventArgs e)
{
var d = (TappedEventArgs)e;
var data = d.Parameter as int;//yor itemID type
}

how do I make a slide effect in a listview? - UWP

I do not know how to do the effect very well, and I know how to capture the StackPanel to which I am going to make the effect. To help me with this last would be very helpful. What I want is to hide all StackPanel from a ListView and only show the element that is clicked on, if it loses focus, it will hide again. Here is the essential.
<ListView Grid.Row="1" ItemsSource="{Binding listOfSomething, Mode=TwoWay}" SelectionChanged="ListView_SelectionChanged">
<!-- rest of code -->
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Margin="0,2,0,2">
<!-- rest of code -->
<StackPanel Grid.Column="2" Grid.RowSpan="2" Background="#FFF" Margin="5,0,0,0">
<Grid Background="Transparent" Height="52">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Background="Transparent" Padding="0,0,0,0">
<StackPanel Padding="0,0,0,0" Margin="0,0,0,0">
<Image Source="ms-appx:///Assets/plus.png" Width="32" Height="32" />
</StackPanel>
</Button>
<Button Grid.Column="1" Background="Transparent" Padding="0,0,0,0">
<StackPanel Padding="0,0,0,0" Margin="0,0,0,0">
<Image Source="ms-appx:///Assets/delete.png" Width="32" Height="32"/>
</StackPanel>
</Button>
</Grid>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I do this approach but I think it's not recommended for long lists as it tries to suspend/maintain the view, but it's worth a shot based on your desired outcome/effect:
So here it is, first of all, create two DataTemplates inside your Page.xaml
<Page.Resources>
<DataTemplate x:Name="normalTemplate" x:Key="normalTemplate">
<!-- Your template view when item is NOT clicked/selected -->
</DataTemplate>
<DataTemplate x:Name="selectedTemplate" x:Key="selectedTemplate">
<!-- Your template view when item is clicked/selected -->
</DataTemplate>
</Page.Resources>
Modify your ListView control with:
<ListView Grid.Row="1" ItemsSource="{Binding listOfSomething, Mode=TwoWay}" SelectionChanged="ListView_SelectionChanged" ItemTemplate="{StaticResource normalTemplate}" />
Then on your ListView_SelectionChanged method, insert/add this lines of code:
try
{
// Assign DataTemplate for selected items
foreach (var item in e.AddedItems)
{
ListViewItem lvi = (sender as ListView).ContainerFromItem(item) as ListViewItem;
lvi.ContentTemplate = (DataTemplate)this.Resources["selectedTemplate"];
}
//Remove DataTemplate for unselected items
foreach (var item in e.RemovedItems)
{
ListViewItem lvi = (sender as ListView).ContainerFromItem(item) as ListViewItem;
lvi.ContentTemplate = (DataTemplate)this.Resources["normalTemplate"];
}
}
catch (Exception ex)
{ }

Xamarin Forms with UWP Refresh causes value to disappear

I have a Xamarin Forms application using Android and UWP. Everything works fine under Android but under UWP I have a problem when I want to modify some values displayed on the screen.
Here is my (simplified) ViewModel (using Fody.PropertyChanged) :
public class SalesViewModel : BaseAppViewModel
{
public ObservableCollection<SaleModel> Sales { get; set; }
= new ObservableCollection<SaleModel>();
[DoNotNotify]
public ICommand AddQuantityCommand => new Command<SaleModel>(item =>
{
item.Quantity += 1;
});
}
The BaseAppViewModel implement the INotifyPropertyChanged interface for Fody.PropertyChanged
The (simplified) SaleModel class:
public class SaleModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public double Quantity { get; set; }
}
And the (part of the) XAML which display the list of SaleModel's
<ListView x:Name="ListView" ItemsSource="{Binding Sales, Mode=TwoWay}" SelectedItem="{Binding SelectedSale, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="arrow.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.AddQuantityCommand, Source={x:Reference Name=SalesPage}}" CommandParameter="{Binding .}" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Column="1" Text="{Binding Quantity, Mode=OneWay}"
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When clicking on the Image, the quantity is incremented but the value disappear from the screen under UWP.
I have tested your code and reproduced your issue. And I written the following ViewCell replace yours. Please try to modify your ViewCell.
<ViewCell>
<StackLayout BackgroundColor="#eee"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="time.jpg" HeightRequest="50" WidthRequest="50" >
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding AddQuantityCommand} " CommandParameter="{Binding .}"/>
</Image.GestureRecognizers>
</Image>
<Label Text="{Binding Quantity}"
TextColor="#f35e20" />
<Label Text="{Binding Quantity}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
</StackLayout>
</StackLayout>
</ViewCell>
I have upload code sample to github. Please refer to.

Horizontal scrollview in XAML

I have a list of MyClass:
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
I would like to display this list in a Horizontal scrollview. Im doing it in XAML and having a hard time finding examples. I got this now:
<ScrollView Orientation="Horizontal">
<ListView x:Name="MyClassList"
ItemsSource="{Binding MyClassList}"
RowHeight="210">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5">
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Name:" LineBreakMode="TailTruncation"></Label>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Name}" LineBreakMode="TailTruncation"></Label>
<Label Grid.Row="1" Grid.Column="0" Text="Type:" LineBreakMode="TailTruncation"></Label>
<Label Grid.Row="1" Grid.Column="1" Text="{Binding Type}" LineBreakMode="TailTruncation"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
But this presents the list in a vertical manner. Any tips on how to scroll this list horizontally?
Not entirely sure if I understand the issue. My interpretation is that you want the ListView itself to add elements horizontally instead of vertically.
This can be achieved by settings the ListViews ItemsPanel to a horizontal StackPanel.
Try this:
<ScrollView Orientation="Horizontal">
<ListView x:Name="MyClassList"
ItemsSource="{Binding MyClassList}"
RowHeight="210">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5">
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Name:" LineBreakMode="TailTruncation"></Label>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Name}" LineBreakMode="TailTruncation"></Label>
<Label Grid.Row="1" Grid.Column="0" Text="Type:" LineBreakMode="TailTruncation"></Label>
<Label Grid.Row="1" Grid.Column="1" Text="{Binding Type}" LineBreakMode="TailTruncation"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
This has been solved with a custom class called ItemsView (not to be confused with Xamarin's ItemsView for data templating in a ListView) which implements a ScrollView/StackPanel pattern. Please see the code: https://gist.github.com/fonix232/b88412a976f67315f915