I'm new to Xamarin. I want to setup a ListView in Xamarin plus 2 buttons to check/uncheck every CheckBox inside the ListView to utilize the checked ones afterwards. Could you please tell me how to access these Checkboxes with kind of a foreach loop?
<ListView x:Name="countryListView" HasUnevenRows="true" ItemTapped="Handle_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Bla" CommandParameter="{Binding .}" />
<MenuItem Text="Delete" IsDestructive="true" CommandParameter="{Binding .}" Clicked="deleteCountry" />
</ViewCell.ContextActions>
<StackLayout Orientation="Horizontal" Padding="5">
<controls:CircleImage HeightRequest="30" WidthRequest="30" Aspect="AspectFill" Source="{Binding imageURL}" VerticalOptions="Center" HorizontalOptions="Center" />
<!--<Image Source="{Binding imageURL}" />-->
<StackLayout HorizontalOptions="StartAndExpand">
<Label Text="{Binding name}" />
<Label Text="{Binding capital}" />
</StackLayout>
<CheckBox x:Name="checkbox" IsChecked="false" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Thanks,
Thomas
Bind the IsChecked property of your checkbox to bool in your ViewModel and in OnClick event make it true or false. Don't forget to implement INotifyPropertyChanged to refresh your UI.
Related
I have carousel view, I want get property color of next object in carousel using XAML. My XAML:
<CarouselView
HeightRequest="300"
PeekAreaInsets="100"
IndicatorView="indicatorView"
ItemsSource="{Binding TrafficColors}">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="False"
CornerRadius="5"
Padding="0"
Margin="10, 0"
WidthRequest="200"
HeightRequest="300"
>
<Frame.Background>
<LinearGradientBrush EndPoint="1,1">
<GradientStop Color="{Binding HEX, StringFormat='#{0}'}" Offset="0.4" />
<GradientStop Color="#CFDEF3" Offset="0.77" />
</LinearGradientBrush>
</Frame.Background>
<!--
<Frame.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type view:EDocsMainPageViewModel}}, Path=GoToEDoc}"
CommandParameter="{Binding Id}"
/>
</Frame.GestureRecognizers>
-->
<StackLayout>
<Label Text="{Binding Name}"
TextColor="Black"
FontSize="22"
Padding="10"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Label Padding="10" Text="{Binding ShiftCode, StringFormat='Номер МЛ:{0}'}" TextColor="Black" FontSize="14" />
<Label Padding="10" Text="{Binding RegDate, StringFormat='Дата:{0:yyyy.MM.dd HH:mm}'}" TextColor="Black" FontSize="14" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
For example, I want get BackgroundColor of next Frame in collection. For example, in HTML I have object ID or class name and by this keys and JS I can get something. What about XAML, can I set key to objects in collection and from XAML in some way get value by this key? I will be thankful for anything information.
P.S. I don`t want add in view model one more property, I want do that in XAML.
For example, I want get BackgroundColor of next Frame in collection.
For example, in HTML I have object ID or class name and by this keys
and JS I can get something. What about XAML, can I set key to objects
in collection and from XAML in some way get value by this key?
We cannot get the BackgroundColor of next Frame in collection, since we don't know which item will be selected. But we can get the currentItem and previousItem.
And we know that the items of the CarouselView use the same DataTemplate of the CarouselView.ItemTemplate, so we cannot get the BackgroundColor of next Frame by the x:Name of the views in the DataTemplate layout.
Since you bind color to property Frame.Background, so you can get the currentItem and previousItem by event OnCurrentItemChanged.
So, I suggest to adding a property (e.g. BackgroundColor) to the Item of your ItemsSource(TrafficColors).
public string BackgroundColor { get; set; }
Then, you will get the currentItem and previousItem in event OnCurrentItemChanged:
For example:
void OnCurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
// here you can get the PreviousItem and CurrentItem which include the property `BackgroundColor`
previousItem = e.PreviousItem as Item;
currentItem = e.CurrentItem as Item;
}
The TestPage.xaml
<CarouselView ItemsSource="{Binding Monkeys}"
CurrentItemChanged="OnCurrentItemChanged"
PositionChanged="OnPositionChanged">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="20"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="Center"
BackgroundColor="{Binding BackgroundColor, Converter = {StaticResource ColorConverter}}"
>
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="20"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
For more information about CarouselView,you can check: Configure CarouselView interaction.
For how to bind color , you can check thread:https://stackoverflow.com/questions/72901517/net-maui-how-to-reference-a-color-in-a-binding .
I have a listview. This list view has 5 rows with two buttons namely A & B. When I tap on button A on a row, I want to change the image on A as well as B on the same row and vice-versa. I am able to individually tap and change the image on the same button but don't know how to change the image on the other button. Here is my listview:
<ListView x:Name="GroupedView" SeparatorColor="Transparent" GroupDisplayBinding="{Binding Title}" IsGroupingEnabled="true" HasUnevenRows="true" >
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="5" BackgroundColor="#E2F5F9">
<Label Text="{Binding Title}" TextColor="{StaticResource NavyBlue}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Spacing="2" Padding="5">
<StackLayout VerticalOptions="FillAndExpand">
<Label Text="{Binding QuestionName}" />
</StackLayout>
<StackLayout IsVisible="{Binding ShowYesNo}" Spacing="15" Orientation="Horizontal" HorizontalOptions="End">
<Button ClassId="Yes" Clicked="ChoiceSelected" CommandParameter="{Binding question_id}" Image="{Binding YesChoiceImg}" />
<Button ClassId="No" Clicked="ChoiceSelected" CommandParameter="{Binding question_id}" Image="{Binding NoChoiceImg}" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I am then using the sender to identify the class ID and change the image of the button.
Should I be using a command? Should I be doing something else? Please help. Thanks
If you want to use the CommandParameter you should be using a Command. At the moment you're mixing 2 different ways to handle the click.
One thing to note though is that if you use a command you usually want to bind it to a Command that is defined on your ViewModel but since inside the DataTemplate your BindingContext is the ListView item instead of the ViewModel so you have to reference around that. Something like this should work:
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Spacing="2" Padding="5">
<StackLayout VerticalOptions="FillAndExpand">
<Label Text="{Binding QuestionName}" />
</StackLayout>
<StackLayout IsVisible="{Binding ShowYesNo}" Spacing="15" Orientation="Horizontal" HorizontalOptions="End">
<Button ClassId="Yes" Command="{Binding Path=BindingContext.ButtonCommand, Source={x:Reference MyQuestionPage}}" CommandParameter="{Binding .} Image="{Binding YesChoiceImg}" />
<Button ClassId="No" Clicked="ChoiceSelected" CommandParameter="{Binding question_id}" Image="{Binding NoChoiceImg}" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
Note here that you have to give your ContentPage an x:Name (so you can reference it and call the BindingContext on it). And the "{Binding .}" binds to the current list item. So no need to search for it on id you can just plug it into the command directly!
I have this .XAML page and Scroll doesn't work
Its working fine when I have remove AbsoluteLayout and take stacklayout.
<ScrollView>
<AbsoluteLayout>
<ListView x:Name="lstView" ItemsSource="{Binding Items}" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1"
ItemSelected="lstView_ItemSelected">
<ListView.Header>
<Label Text="Store Allocation" BackgroundColor="White" TextColor="Black" FontAttributes="Bold" HorizontalOptions="Fill" HorizontalTextAlignment="Center" />
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}" Height="200" Detail="{Binding Detail}" DetailColor="Black" TextColor="Red" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<BoxView AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" BackgroundColor="LightGray" Opacity="0.7" InputTransparent="False" IsVisible="{Binding Path=IsBusy, Source={x:Reference Page}}" />
<ActivityIndicator IsRunning="{Binding Path=IsBusy, Source={x:Reference Page}}" AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds=".5,.5,-1,-1" />
</AbsoluteLayout>
</ScrollView>
Your XAML basically "says" put a ScrollView on the page, with an AbsoluteLayout filling that ScrollView. Since the inner layout perfectly fits the ScrollView there is no need to scroll. Moreover the ListView and the BoxView are set to take the whole AbsoluteLayout (AbsoluteLayout.LAyoutBounds="0,0,1,1"), no more no less. Why should the ScrollView scroll?
Furthermore, if it worked that way, you'd scroll the ActivityIndicator with everything else, which is supposedly not what you want. I'd assume that you'd like to keep the ActivityIndicator in place, on top of the ListView.
What you could try (I'm not 100% sure, but it should work) is wrapping the ListView only with the ScrollView and put the ScrollView in the AbsoluteLayout this way, the ScrollView will recognize the ListView being too large for the screen and enable scrolling, while everything else stays in place:
<AbsoluteLayout>
<ScrollView AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<ListView x:Name="lstView" ItemsSource="{Binding Items}"
ItemSelected="lstView_ItemSelected">
<ListView.Header>
<Label Text="Store Allocation" BackgroundColor="White" TextColor="Black" FontAttributes="Bold" HorizontalOptions="Fill" HorizontalTextAlignment="Center" />
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}" Height="200" Detail="{Binding Detail}" DetailColor="Black" TextColor="Red" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
<BoxView AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" BackgroundColor="LightGray" Opacity="0.7" InputTransparent="False" IsVisible="{Binding Path=IsBusy, Source={x:Reference Page}}" />
<ActivityIndicator IsRunning="{Binding Path=IsBusy, Source={x:Reference Page}}" AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds=".5,.5,-1,-1" />
</AbsoluteLayout>
You can also manually set the height of your AbsoluteLayout.
<ScrollView>
<AbsoluteLayout HeightRequest="800">
<!--Page Contents-->
</AbsoluteLayout>
</ScrollView>
How set the item in ContextActions. In my example I want to set default car.
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Ustaw domyslny" Command="{Binding DefultCarCommand}" CommandParameter="{Binding .}"/>
</ViewCell.ContextActions>
<StackLayout>
<Label Text="{Binding RegistrationNumber}" />
<Label Text="{Binding Brand}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
In ViewModel I use DelegateCommand
public DelegateCommand DefultCarCommand { get; private set; }
Now it does not work and I do not know why
Please note BindingContext of MenuItem is the Single Model that you bind in ItemSource of ListView not the whole ViewModel. You need to use reference binding to bind to ViewModel properties like this:
<ListView x:Name="MyListView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Ustaw domyslny" Command="{Binding Path=BindingContext.DefultCarCommand, Source={x:Reference Name=MyListView}}" CommandParameter="{Binding .}"/>
</ViewCell.ContextActions>
<StackLayout>
<Label Text="{Binding RegistrationNumber}" />
<Label Text="{Binding Brand}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I don't know why, but when I tap any ListView item, the Button inside it's template loses the background color.
I use default ViewCell inside ListView. Is this a Xamarin.Forms bug?
I have this problem only on iOS.
<ListView x:Name="lv" Grid.Row="2" HasUnevenRows="true" BackgroundColor="White" ItemTapped="OnItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="16" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="{Binding .,Converter={StaticResource IndexColorConverter}">
<StackLayout VerticalOptions="Center">
<Label Text="{Binding Auditorium}" FontSize="18" TextColor="Black"/>
<ContentView Padding="0,-5,0,0">
<Label Text="{Binding Title}" FontSize="16" TextColor="Black"/>
</ContentView>
<StackLayout Orientation="Horizontal">
<Button WidthRequest="100" Text="{Binding ButtonOverviewText}" TextColor="White" BackgroundColor="{Binding ButtonColor}" CommandParameter="{Binding .}" Clicked="Handle_Clicked"/>
<Button WidthRequest="100" Text="{Binding ButtonOverviewText}" TextColor="White" BackgroundColor="{Binding ButtonColor}" CommandParameter="{Binding .}" Clicked="Handle_Clicked" />
</StackLayout>
</StackLayout>
<Label Text="{Binding Coordinator}" FontSize="14" TextColor="Gray"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
There was an old issue that I filed fora similar bug: https://bugzilla.xamarin.com/show_bug.cgi?id=27502.
However, the specific scenario you mention is expected behavior on iOS and happens in native (non-Xamarin.Forms) projects too. See the comment here. You might consider disabling the UITableViewCellSelectionStyle of your cells with UITableViewCellSelectionStyle.None. Here is an example of a cell renderer. You can set the cell.SelectionStyle here. This would stop the gray highlight of the cell. If you don't want that it could be a workaround to keep your button colors.
My workaround for this problem is the following.
<Grid>
<BoxView BackgroundColor="{Binding ButtonColor}"/>
<Button Text="{Binding ButtonOverviewText}" TextColor="White" BackgroundColor="Transparent" CommandParameter="{Binding .}" Clicked="Handle_Clicked"/>
</Grid>