How to add a switch in Xamarin Shell MenuItem - xamarin.forms

I want to have a switch in a menuItem of my AppShell.xaml (in addition to the usual text and icon). How can I do that while keeping the styles of the MenuItem ?
I used a DataTemplate in the Shell.MenuItemTemplate of my MenuItem but the result is just ugly as all the styles of the MenuItem are lost. The MenuItem created this way does not have the same font, text color, and font size than the other FlyoutItems and MenuItems of the Shell.
<MenuItem Text="MyMenuItem" Command="{Binding SwitchMode}">
<Shell.MenuItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
<Label Text="{Binding Text}"/>
<Switch IsToggled="{Binding IsModeActivated}"/>
</StackLayout>
</DataTemplate>
</Shell.MenuItemTemplate>

Use element Shell.MenuItemTemplate with reference to DataTemplate defined in Resources.
Common/shared element property values can be defined in a "BaseStyle", while menu specific properties can be defined in styles based on the "BaseStyle":
<Shell.Resources>
...
<Style x:Key="labelBaseStyle" TargetType="Label">
<Setter Property="VerticalTextAlignment" Value="Center" />
</Style>
<Style x:Key="firstMenuLabelStyle" TargetType="Label" BasedOn="{StaticResource labelBaseStyle}">
<Setter Property="FontAttributes" Value="Italic" />
</Style>
<Style x:Key="menuLabelStyle" TargetType="Label" BasedOn="{StaticResource labelBaseStyle}">
<Setter Property="FontAttributes" Value="Bold" />
</Style>
<DataTemplate x:Key="firstMenuItemTemplate">
<StackLayout ...
<Label Style="{StaticResource firstMenuLabelStyle}" ...
</DataTemplate>
<DataTemplate x:Key="menuItemTemplate">
<StackLayout ...
<Label Style="{StaticResource menuLabelStyle}" ...
</DataTemplate>
...
</Shell.Resources>
...
<MenuItem Text="MenuItem1" Shell.MenuItemTemplate="{StaticResource firstMenuItemTemplate}" />
<MenuItem Text="MenuItem2" Shell.MenuItemTemplate="{StaticResource menuItemTemplate}" />

Related

How to make behavior binding on customer control in Xamarin form or dotnet maui?

I created a customer entry which contain a label for error message
<Grid xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ExampleApp.Contols.CustomerEntry"
Title="Customer"
x:Name="AppEntry">
<Entry x:Name="ControlEntry"
BackgroundColor="{Binding BackgroundColor, Source={x:Reference AppEntry}}"/>
<Label x:Name="ConrolErrorMessage"
Text="{Binding ErrorMessage, Source={x:Reference AppEntry}}"/>
</Grid>
Now using the control, in any page.
<CustomerEntry
x:Name="Password"
BackgroundColor="Blue">
<controls:EntryControl.Behaviors>
<toolkit:TextValidationBehavior
InvalidStyle="{StaticResource InvalidEntry}"
MinimumLength="10"
MaximumLength="100" />
</controls:EntryControl.Behaviors>
</CustomerEntry>
The InvalidEntry style is simple:
<Style
x:Key="InvalidEntry"
TargetType="controls:CustomerEntry">
<Setter Property="BackgroundColor" Value="Red" />
</Style>
Now the behavior is not working. Is it possible to bind pass the behavior to the Entry of the customer control?
I try to make the entry of the customer control as follow:
<Entry x:Name="ControlEntry"
BackgroundColor="{Binding BackgroundColor, Source={x:Reference AppEntry}}"
Behaviors="{Binding Behaviors, Source={x:Reference AppEntry}}"/>
The above code didn't work.

How do I expose MultiValidationBehavior's children in custom control?

I'm creating a custom control for an entry that can be validated.
I did this by creating a ContentView that has a Grid as it's child that contains the entry, error label, etc.
I'd like this to be flexible when it comes to validation, so ideally it would be nice to expose the Entry's MultiValidationBehavior's Children property, or set that property as my control's content property.
As it stands now, I haven't figured out a way to add behaviors to my custom control.
Is this possible?
<ContentView x:Class="MPK.UI.Views.Components.FormEntry"
x:Name="FormEntryControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xmlns:yummy="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
xmlns:converters="clr-namespace:MPK.UI.Converters;assembly=MPK.UI">
<ContentView.Resources>
<ResourceDictionary>
<converters:IsValidToEntryBorderConverter x:Key="IsValidToEntryBorderConverter"/>
<converters:ErrorsToLabelTextConverter x:Key="ErrorsToLabelTextConverter"/>
<xct:InvertedBoolConverter x:Key="InvertedBoolConverter" />
</ResourceDictionary>
</ContentView.Resources>
<Grid>
<yummy:PancakeView CornerRadius="10"
HeightRequest="50"
HorizontalOptions="FillAndExpand"
BackgroundColor="{StaticResource EntryBackgroundColor}"
Padding="16,0,16,0">
<yummy:PancakeView.Behaviors>
<xct:AnimationBehavior AnimateCommand="{Binding Source={x:Reference FormEntryControl}, Path=ShakeCommand}">
<xct:AnimationBehavior.AnimationType>
<xct:ShakeAnimation />
</xct:AnimationBehavior.AnimationType>
</xct:AnimationBehavior>
</yummy:PancakeView.Behaviors>
<yummy:PancakeView.Border>
<yummy:Border
Color="{Binding IsValid, Source={x:Reference MultiValidationBehavior}, Converter={StaticResource IsValidToEntryBorderConverter}}"
Thickness="1" />
</yummy:PancakeView.Border>
<Entry x:Name="Entry"
Text="{Binding Text, Source={x:Reference FormEntryControl}}"
Placeholder="{Binding Placeholder, Source={x:Reference FormEntryControl}}"
ReturnType="{Binding ReturnType, Source={x:Reference FormEntryControl}}"
ReturnCommand="{Binding ReturnCommand, Source={x:Reference FormEntryControl}}"
PlaceholderColor="{StaticResource EntryPlaceholderTextColor}"
BackgroundColor="Transparent"
IsPassword="{Binding IsPassword, Source={x:Reference FormEntryControl}}"
ClearButtonVisibility="{Binding ClearButtonVisibility, Source={x:Reference FormEntryControl}}">
<Entry.Effects>
<xct:RemoveBorderEffect />
</Entry.Effects>
<Entry.Behaviors>
<xct:MultiValidationBehavior x:Name="MultiValidationBehavior"
IsValid="{Binding IsValid, Source={x:Reference FormEntryControl}, Mode=TwoWay}"
Children="{Binding ValidationBehaviors, Source={x:Reference FormEntryControl}}"/>
<!-- Binding children doesn't work here -->
</Entry.Behaviors>
</Entry>
</yummy:PancakeView>
<xct:Expander Margin="8,4,0,0"
AnimationLength="100"
IsExpanded="{Binding IsValid, Source={x:Reference FormEntryControl}, Mode=OneWay, Converter={StaticResource InvertedBoolConverter}}">
<Label Text="{Binding Errors, Source={x:Reference MultiValidationBehavior}, Converter={StaticResource ErrorsToLabelTextConverter}}"
TextColor="{StaticResource ErrorColor}" />
</xct:Expander>
</Grid>
</ContentView>
The solution was much simpler than I expected.
In my control's code behind I needed to add a property that points to the multivalidationbehavior's children property.
public IList<ValidationBehavior> ValidationBehaviors => TheMultiValidationBehavior.Children;
Using my custom control looks something like this:
<components:FormEntry Placeholder="Name">
<components:FormEntry.ValidationBehaviors>
<xct:TextValidationBehavior MinimumLength="1" xct:MultiValidationBehavior.Error="Min: 1"/>
</components:FormEntry.ValidationBehaviors>
</components:FormEntry>

Xamarin forms 5.0 CollectionView Drag appearence multiple items

Good afternoon.
I am using a CollectionView in Xamarin forms 5.0
I already succed to "transfert" 2 or more items from one CollectionView to an other one in the same window using SelectionMode="Multiple".
For my test, i just use and customize a good example founded on the web: https://github.com/CrossGeeks/DragAndDropXFSample
What i'm trying to do concern the appearance of the dragged items.
Because i add a DragGestureRecognizer inside my CollectionView.ItemTemplate.DataTemplate
on my first collection view and a DropGestureRecognizer inside my CollectionView.ItemTemplate.DataTemplate second collection view, the drag & drop functionnality work well.
But, the animation draw only the item i touched, not all the selected ones.
Does anybody has an idea to manage that ?
Is it even possible?
Anyway, thanks for reading and maybe your help ;-)
The xaml page:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
x:Class="DragAndDropXFSample.EventsPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<ContentPage.Content>
<StackLayout Padding="20,40" BackgroundColor="Black">
<Label
FontAttributes="Bold"
FontSize="Large"
Text="Hi John" />
<Label Text="Your schedule Today" />
<Frame Margin="0,20,0,0" BackgroundColor="White">
<StackLayout>
<CollectionView
x:Name="EventsCollection"
ItemsSource="{Binding Events}"
SelectionMode="Multiple">
<CollectionView.EmptyView>
<Label Text="You have no events" VerticalOptions="CenterAndExpand" />
</CollectionView.EmptyView>
<CollectionView.ItemsLayout>
<GridItemsLayout
HorizontalItemSpacing="10"
Orientation="Vertical"
Span="2"
VerticalItemSpacing="10" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame
Padding="0"
BackgroundColor="{Binding Color}"
HasShadow="False">
<Frame.Style>
<Style TargetType="Frame">
<!-- To visualy show the selection to the user -->
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="CadetBlue" />
<Setter TargetName="uiTime" Property="Label.FontAttributes" Value="Italic" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</Frame.Style>
<StackLayout Padding="10,10,10,0" Spacing="10">
<Label
x:Name="uiTime"
FontAttributes="Bold"
FontSize="Large"
Text="{Binding Time, StringFormat='{0:HH:mm}'}" />
<Label FontSize="15" Text="{Binding Title}" />
<Label
FontSize="Caption"
Text="{Binding Location, StringFormat='At {0}'}"
TextColor="White" />
<StackLayout
Margin="-10,0"
Padding="5"
BackgroundColor="#66000000"
Orientation="Horizontal">
<Image
HeightRequest="20"
HorizontalOptions="EndAndExpand"
Source="ic_edit" />
<Label
FontSize="Caption"
Text="Edit"
TextColor="White"
VerticalOptions="Center" />
</StackLayout>
</StackLayout>
<Frame.GestureRecognizers>
<DragGestureRecognizer DragStartingCommand="{Binding Path=BindingContext.DragStartingCommand, Source={x:Reference EventsCollection}}" DragStartingCommandParameter="{Binding SelectedItems, Source={x:Reference EventsCollection}}" />
</Frame.GestureRecognizers>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CollectionView x:Name="EventsCollection2" ItemsSource="{Binding Events2}">
<CollectionView.EmptyView>
<Label Text="You have no events" VerticalOptions="CenterAndExpand" />
</CollectionView.EmptyView>
<CollectionView.ItemsLayout>
<GridItemsLayout
HorizontalItemSpacing="10"
Orientation="Vertical"
Span="2"
VerticalItemSpacing="10" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame
Padding="0"
BackgroundColor="{Binding Color}"
HasShadow="False">
<StackLayout Padding="10,10,10,0" Spacing="10">
<Label
x:Name="uiTime2"
FontAttributes="Bold"
FontSize="Large"
Text="{Binding Time, StringFormat='{0:HH:mm}'}" />
<Label FontSize="15" Text="{Binding Title}" />
<Label
FontSize="Caption"
Text="{Binding Location, StringFormat='At {0}'}"
TextColor="White" />
<StackLayout
Margin="-10,0"
Padding="5"
BackgroundColor="#66000000"
Orientation="Horizontal">
<Image
HeightRequest="20"
HorizontalOptions="EndAndExpand"
Source="ic_edit" />
<Label
FontSize="Caption"
Text="Edit"
TextColor="White"
VerticalOptions="Center" />
</StackLayout>
</StackLayout>
<Frame.GestureRecognizers>
<DropGestureRecognizer DropCommand="{Binding BindingContext.DropOverList2Command, Source={x:Reference EventsCollection2}}" />
</Frame.GestureRecognizers>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</Frame>
</StackLayout>
</ContentPage.Content>
</ContentPage>
The view model class :
public class EventsPageViewModel
{
private IList<Event> _dragEvent;
/// <summary>
/// It's a Command<IList<object>> beacause of the Selectionmode.Multiple
/// </summary>
public ICommand DragStartingCommand => new Command<IList<object>>((param) =>
{
_dragEvent = new List<Event>(param.Cast<Event>());
});
public ICommand DropOverList2Command => new Command(() =>
{
foreach (var e in _dragEvent)
{
if (Events.Contains(e))
{
Events.Remove(e);
Events2.Add(e);
}
}
});
public ObservableCollection<Event> Events { get; }
public ObservableCollection<Event> Events2 { get; }
public EventsPageViewModel()
{
Events = new ObservableCollection<Event>()
{
{new Event("Go for a walk", "Home", DateTime.Now.AddHours(3), Color.OrangeRed) },
{new Event("Finish PR", "Work", DateTime.Now.AddHours(5), Color.ForestGreen) },
{new Event("Watch a movie", "Home", DateTime.Now.AddMinutes(40), Color.LightSkyBlue) },
};
Events2 = new ObservableCollection<Event>()
{
{new Event("Go for a walk2", "Home", DateTime.Now.AddHours(3), Color.GreenYellow) }
};
}
}
Edit :
I cannot make video but i 've made some screenshots.
Initial state:
Nothing selected, the top collection view is the source, and the bottom collection view is the dest
I select the first item in the top collection view
I select a second item in the top CollectionView
I start dragging by touching and moving the first selected item
the expected result would be something like :
EDIT:
I find something interresting called Windows.UI.Xaml.DragEventArgs.DragUIOverride
see here but apparently it is for uwp, does anybody know if there is an equivalent for Android/iOS ? Thanks for your time

Is it possible to have a tab inside of a page in XamarinForm?

I typed "tab" and the only thing that seems to be relavent in the IntelliSense was "TabbedPage". I searched Google, and it also only showed tabbed page.
But what if I want something else above the tab? Something like this? Is this achievable in Xamarin Form? It is possible in native Android.
--------------------
Text inputs, buttons
---------------------
tabbed or swipe-able
content
--------------------
TabbedPage is a Page, is not a View so you can't include it inside another page.
On GitHub there is some TabView you can use. For example XFControls
<ctrls:TabView.TabTemplate>
<DataTemplate>
<StackLayout>
<ctrls:FontIcon Glyph="{Binding Glyph}"
FontFamily="{StaticResource font}"
FontSize="25"
Color="Gray"
HorizontalOptions="Center"
>
<ctrls:FontIcon.Triggers>
<DataTrigger TargetType="ctrls:FontIcon"
Binding="{Binding IsSelected}"
Value="True"
>
<Setter Property="Color" Value="Red" />
</DataTrigger>
</ctrls:FontIcon.Triggers>
</ctrls:FontIcon>
<Label Text="{Binding Title}"
TextColor="Gray"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
FontSize="10">
<Label.Triggers>
<DataTrigger TargetType="Label"
Binding="{Binding IsSelected}"
Value="True"
>
<Setter Property="TextColor" Value="Red" />
</DataTrigger>
</Label.Triggers>
</Label>
</StackLayout>
</DataTemplate>
</ctrls:TabView.TabTemplate>
<ctrls:TabView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}"
HorizontalOptions="Center" />
</DataTemplate>
</ctrls:TabView.ItemTemplate>
</ctrls:TabView>

How to write the Style for check box place in the GridCell UWP?

enter image description here
I have tried to write the style for check box placed in the Grid cell by setting the target type as checkbox, but its apply the style also for the filter checkbox. could anybody suggest me to write the style only for the Grid cell check box.
Please find the image attached above i have write a style only for the checkbox loaded in the grid cell instead of the applying to all
I tried it by this way
<Page.Resources>
<Style TargetType="CheckBox">
<Setter Property="Background" Value="Red"/>
</Style>
</Page.Resources>
<Page.DataContext>
<local:ViewModel/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<my:SfDataGrid ItemsSource="{Binding Orders}" AllowFiltering="True" />
</Grid>
You have to use Column property of DataGridCell and check its DisplayIndex value and write a DataTrigger.
Sample approach :
<DataGrid ...>
<DataGrid.Resources>
<Style TargetType="CheckBox">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Column.DisplayIndex, RelativeSource={RelativeSource AncestorType=DataGridCell, Mode=FindAncestor}}" Value="0">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
Ok. #BalamuruganR I've made a simple code sample for you. Using the GridTemplateColumn and specify a "x:Key" for your custom style. Please check the following code sample:
<Page.Resources>
<Style x:Key="CheckBoxStyle1" TargetType="CheckBox">
<Setter Property="Background" Value="Red" />
</Style>
<DataTemplate x:Key="cellTemplate">
<CheckBox Content="DataGrid" IsChecked="{Binding Flag}" Style="{StaticResource CheckBoxStyle1}"></CheckBox>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<syncfusion:SfDataGrid x:Name="sfGrid" Grid.Column="0"
AllowGrouping="True"
AutoExpandGroups="True"
ShowGroupDropArea="True"
AllowEditing="True"
AllowFiltering="True"
AutoGenerateColumns="False"
ItemsSource="{Binding UserDetails}">
<syncfusion:SfDataGrid.Columns>
<syncfusion:GridTextColumn MappingName="UserId" />
<syncfusion:GridTextColumn MappingName="Name" />
<syncfusion:GridDateTimeColumn MappingName="DateofBirth" />
<syncfusion:GridNumericColumn MappingName="ContactNo" />
<syncfusion:GridTemplateColumn MappingName="Flag" CellTemplate="{StaticResource cellTemplate}" />
</syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
</Grid>

Resources