I am using Xamarin.Forms Shell Layout, with a Flyout menu using Custom subclassed FlyoutItem called CustomFlyoutItem, the display of which is controlled with a dataitem template. The template uses a Grid and contains two rows. The second row is just a pink bottom border (BoxView height 1) and should only be displayed if my customFlyoutItem's bool property HasBottomDivider is set to true. (Using the IsVisible binding to achieve this).
There are two issues: 1) The last item in the flyout item should be the "help" item in my screenshot. However the list appears to contain one extra phantom CustomFlyoutItem with no icon or text. On debugging I see this is an item of the type "ShellGroupItem"
2) the item is getting a pink border under it too somehow which is the main issue really.
I have a workaround to remove the item using linq before the page is displayed, but I would like to know the root cause of why it is there in the first place.
<Shell.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.05*"></ColumnDefinition>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
<ColumnDefinition Width="0.85*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="1" />
</Grid.RowDefinitions>
<Label Text="{Binding Ligature}"
Grid.Column="1"
Grid.Row="0"
TextColor="White"
FontFamily="{Binding FontFamily }"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start"
FontSize="20"
HeightRequest="45">
</Label>
<Label Grid.Column="2"
Grid.Row="0"
FontSize="16"
Margin="0"
Text="{Binding Title}"
TextColor="White"
HorizontalTextAlignment="Start"
VerticalTextAlignment="Center" />
<BoxView IsVisible="{Binding HasBottomDivider}"
BackgroundColor="{StaticResource BrilliantRose}"
Grid.Column="0" Grid.ColumnSpan="3"
Grid.Row="1" >
</BoxView>
</Grid>
</DataTemplate>
</Shell.ItemTemplate>
<Shell.FlyoutHeader>
<menu:FlyoutHeader />
</Shell.FlyoutHeader>
<menu:CustomFlyoutItem Title="Home" FontFamily="{StaticResource FontAwesomeSolid}" Ligature="{x:Static fontawesome:FontAwesomeIcons.Home}">
<Tab>
<ShellContent>
<views:LoginPage />
</ShellContent>
</Tab>
</menu:CustomFlyoutItem>
<menu:CustomFlyoutItem HasBottomDivider="true" Title="Measurements" FontFamily="{StaticResource FontAwesomeRegular}" Ligature="{x:Static fontawesome:FontAwesomeIcons.ChartBar}">
<Tab>
<ShellContent>
<views:LoginPage />
</ShellContent>
</Tab>
</menu:CustomFlyoutItem>
<menu:CustomFlyoutItem Title="Jobs" FontFamily="{StaticResource FontAwesomeSolid}" Ligature="{x:Static fontawesome:FontAwesomeIcons.User}">
<Tab>
<ShellContent>
<views:LoginPage />
</ShellContent>
</Tab>
</menu:CustomFlyoutItem>
<menu:CustomFlyoutItem HasBottomDivider="true" Title="Instruments" FontFamily="{StaticResource FontAwesomeBrands}" Ligature="{x:Static fontawesome:FontAwesomeIcons.BluetoothB}">
<Tab>
<ShellContent>
<views:LoginPage />
</ShellContent>
</Tab>
</menu:CustomFlyoutItem>
<menu:CustomFlyoutItem Title="Settings" FontFamily="{StaticResource FontAwesomeSolid}" Ligature="{x:Static fontawesome:FontAwesomeIcons.Cog}">
<Tab>
<ShellContent>
<views:LoginPage />
</ShellContent>
</Tab>
</menu:CustomFlyoutItem>
<menu:CustomFlyoutItem Title="Help" FontFamily="{StaticResource FontAwesomeSolid}" Ligature="{x:Static fontawesome:FontAwesomeIcons.QuestionCircle}">
<Tab>
<ShellContent>
<views:LoginPage />
</ShellContent>
</Tab>
</menu:CustomFlyoutItem>
public class CustomFlyoutItem : FlyoutItem
{
public string FontFamily { get; set; }
public string Ligature { get; set; } = "";
public bool HasBottomDivider { get; set; } = false;
}
Related
I have a page with a collection view. I have a button that allows the user to generate a pdf from the collection view data and share the pdf. the generation process takes a few seconds because there is a lot of data so I thought I should show something like a progress bar or progress ring to keep the user waiting and do nothing during this process. I tried to show something like a pop up using content view. this is the code: of the content view:
<ContentView x:Name="popupLoadingView" BackgroundColor="Transparent" Padding="10, 0" IsVisible="false" HorizontalOptions="Center" VerticalOptions="Center">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<StackLayout Orientation="Vertical" HeightRequest="150" WidthRequest="200" BackgroundColor="White">
<ActivityIndicator x:Name="activityIndicator" Margin="0,50,0,0" VerticalOptions="Center" HorizontalOptions="Center" Color="Black" WidthRequest="30" HeightRequest="30" ></ActivityIndicator>
<Label x:Name="lblLoadingText" TextColor="Black" VerticalOptions="Center" HorizontalOptions="Center" VerticalTextAlignment="Center" Text="Loading..."></Label>
</StackLayout>
</StackLayout>
</ContentView>
and this is the code of my collection view
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="isc_alphaApp.Inventory">
<ContentPage.ToolbarItems >
<ToolbarItem Order="Secondary"
Text="logout"
Priority="2"
/>
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<Style TargetType="Grid">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor"
Value="#ffc40c" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout >
<SearchBar HorizontalOptions="FillAndExpand" x:Name="search" BackgroundColor="#ffc40c"/>
<CollectionView x:Name="lstl"
SelectionChanged="lstl_SelectionChanged"
SelectionMode="Single"
>
<CollectionView.Header>
<Grid Padding="2" ColumnSpacing="1" RowSpacing="1" >
<Grid.RowDefinitions>
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.7*" />
<ColumnDefinition Width="0.3*"/>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text="Code"
FontAttributes="Bold"
LineBreakMode="TailTruncation"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="Black"/>
<Label Grid.Column="1"
Text="Description"
FontAttributes="Bold"
LineBreakMode="TailTruncation"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="Black"/>
<Label
TextColor="Black"
Grid.Column="2"
Text="Unit"
LineBreakMode="TailTruncation"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="Center"
/>
<Label
Grid.Column="3"
Text="Qty"
LineBreakMode="TailTruncation"
FontAttributes="Bold"
HorizontalOptions="Center"
TextColor="Black"
VerticalOptions="Center"
/>
<Label
TextColor="Black"
Grid.Column="4"
Text="U.Price"
LineBreakMode="TailTruncation"
FontAttributes="Bold"
HorizontalOptions="Center"
VerticalOptions="Center"
/>
</Grid>
</CollectionView.Header>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="1" ColumnSpacing="1" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.7*" />
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Label HorizontalOptions="Center"
Grid.Column="0"
TextColor="Black"
Text="{Binding itemcode}"
VerticalOptions="Center"
LineBreakMode="TailTruncation" />
<Label
Grid.Column="1"
VerticalOptions="Center"
HorizontalOptions="Center"
TextColor="Black"
Text="{Binding name}"
LineBreakMode="TailTruncation" />
<Label
Grid.Column="2"
TextColor="Black"
Text="{Binding itemsunitcode}"
LineBreakMode="TailTruncation"
VerticalOptions="Center"
HorizontalOptions="Center"
FontAttributes="Italic"
/>
<Label
TextColor="Black"
Grid.Column="3"
VerticalOptions="Center"
HorizontalOptions="Center"
Text="{Binding currentQuantity}"
LineBreakMode="TailTruncation"
FontAttributes="Italic"
/>
<Label
Grid.Column="4"
TextColor="Black"
Text="{Binding CostPrice}"
LineBreakMode="TailTruncation"
VerticalOptions="Center"
HorizontalOptions="Center"
FontAttributes="Italic"
/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<StackLayout VerticalOptions="EndAndExpand" HorizontalOptions="FillAndExpand" Orientation="Horizontal" BackgroundColor="#ffc40c">
<StackLayout Style="{StaticResource ButtonNavigationBarStackLayoutStyle}" x:Name="stckcol">
<Image Margin="0,10,0,10" x:Name="imgAdd" Style="{StaticResource ButtonNavigationBarImageStyle}" />
<Label Text="del" Style="{StaticResource ButtonNavigationBarLabelStyle}" x:Name="col_add_remove"></Label>
</StackLayout>
<StackLayout Style="{StaticResource ButtonNavigationBarStackLayoutStyle}" x:Name="stckfilter">
<Image Margin="0,10,0,10" x:Name="imgfilter" Style="{StaticResource ButtonNavigationBarImageStyle}" />
<Label Text="Filter" Style="{StaticResource ButtonNavigationBarLabelStyle}"></Label>
</StackLayout>
<StackLayout Style="{StaticResource ButtonNavigationBarStackLayoutStyle}" x:Name="stckshare">
<Image Margin="0,10,0,10" x:Name="imgshare" Style="{StaticResource ButtonNavigationBarImageStyle}" />
<Label Text="Share" Style="{StaticResource ButtonNavigationBarLabelStyle}"></Label>
</StackLayout>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
i tried adding the content view code at the beginning of the collection view code, but it doesn't appear in the place intended. i want it to appear like an alert on top of the collection view layout and in the middle of the screen. this is the code of the pdf generation:
shareTap.Tapped += (sender, e) =>
{
popupLoadingView.IsVisible = true;
activityIndicator.IsRunning = true;
requestPermission();
};
async public void requestPermission()
{
var newstatus= Plugin.Permissions.Abstractions.PermissionStatus.Unknown;
var status = Plugin.Permissions.Abstractions.PermissionStatus.Unknown;
status = await CrossPermissions.Current.CheckPermissionStatusAsync<StoragePermission>();
if (status != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
{
newstatus = await CrossPermissions.Current.RequestPermissionAsync<StoragePermission>();
if (newstatus == Plugin.Permissions.Abstractions.PermissionStatus.Granted)
{
generatePdf();
}
}
else
{
generatePdf();
}
}
private void generatePdf()
{
try
{
PdfDocument document = new PdfDocument();
//Add a new PDF page.
PdfPage page = document.Pages.Add();
//Get the font file as stream.
Stream fontStream = typeof(MainPage).GetTypeInfo().Assembly.GetManifestResourceStream("isc_alphaApp.Assets.arial.ttf");
//Create a new PdfTrueTypeFont instance.
PdfTrueTypeFont font = new PdfTrueTypeFont(fontStream, 14);
//Create a new bold stylePdfTrueTypeFont instance.
PdfTrueTypeFont boldFont = new PdfTrueTypeFont(fontStream, 14, PdfFontStyle.Bold);
page.Graphics.DrawString("Items", boldFont, PdfBrushes.Black, PointF.Empty);
//Create PdfGrid.
PdfGrid pdfGrid = new PdfGrid();
List<items_display> list_pdf = new List<items_display>();
for (int i = 0; i < list_total.Count; i++)
{
list_pdf.Add(new items_display { Code = list_total[i].itemcode, Description = list_total[i].name, Unit = list_total[i].itemsunitcode, Qty = list_total[i].currentQuantity, Price = list_total[i].CostPrice });
}
//Add values to list
List<items_display> data = list_pdf;
//Add list to IEnumerable.
IEnumerable<items_display> dataTable = data;
PdfStringFormat format_eng = new PdfStringFormat();
format_eng.TextDirection = PdfTextDirection.LeftToRight;
format_eng.Alignment = PdfTextAlignment.Center;
//Assign data source.
pdfGrid.DataSource = dataTable;
pdfGrid.Headers[0].Cells[0].StringFormat = format_eng;
pdfGrid.Headers[0].Cells[1].StringFormat = format_eng;
pdfGrid.Headers[0].Cells[2].StringFormat = format_eng;
pdfGrid.Headers[0].Cells[3].StringFormat = format_eng;
pdfGrid.Headers[0].Cells[4].StringFormat = format_eng;
//Assign bold font to pdfGrid header.
pdfGrid.Headers[0].Style.Font = boldFont;
//Assign font to PdfGrid.
pdfGrid.Style.Font = font;
Regex regex = new Regex("[\u0600-\u06ff]|[\u0750-\u077f]|[\ufb50-\ufc3f]|[\ufe70-\ufefc]");
//Create String format with RTL text direction and center text alignment.
PdfStringFormat format = new PdfStringFormat();
format.TextDirection = PdfTextDirection.RightToLeft;
format.Alignment = PdfTextAlignment.Center;
for (int i = 0; i < data.Count; i++)
{
if (regex.IsMatch(data[i].Code))
{
pdfGrid.Rows[i].Cells[0].StringFormat = format;
}
else
{
pdfGrid.Rows[i].Cells[0].StringFormat = format_eng;
}
if (regex.IsMatch(data[i].Description))
{
pdfGrid.Rows[i].Cells[1].StringFormat = format;
}
else
{
pdfGrid.Rows[i].Cells[1].StringFormat = format_eng;
}
if (regex.IsMatch(data[i].Unit))
{
pdfGrid.Rows[i].Cells[2].StringFormat = format;
}
else
{
pdfGrid.Rows[i].Cells[2].StringFormat = format_eng;
}
pdfGrid.Rows[i].Cells[3].StringFormat = format_eng;
pdfGrid.Rows[i].Cells[4].StringFormat = format_eng;
}
//Assign string format to draw RTL text with center alsignment
//pdfGrid.Rows[0].Cells[1].StringFormat = format;
//pdfGrid.Rows[1].Cells[1].StringFormat = format;
//Draw grid to the page of PDF document.
pdfGrid.Draw(page, new Syncfusion.Drawing.PointF(0, 20));
String file_Path;
string path = DependencyService.Get<getpath>().path();
file_Path = System.IO.Path.Combine(path.ToString(), "items.pdf");
FileStream stream = new FileStream(file_Path, FileMode.Create);
document.Save(stream);
//Close the document
document.Close(true);
Share.RequestAsync(new ShareFileRequest
{
Title = "Share PDF",
File = new ShareFile(file_Path)
});
}
catch(Exception exp)
{
DisplayAlert("No Space", "Not Enough Storage!", "Okay");
}
}
The place where I try to make the content view visible doesn't seem to be right too because it is not displayed until the pdf is already generated. I want it to appear once the user clicks the button.
You would need to make some changes to make it work
You need to use an AbsoluteLayour or Grid on your Inventory page. Because they allow "Stacking" views one on top of the other. Also here you need to add your loading screen.
If your popupLoadingView is in another XAML, you need to add it to your page
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local=" <Insert your namespace here"
x:Class="isc_alphaApp.Inventory">
<!-- Rest of your code-->
<ContentPage.Content>
<Grid>
<local:popupLoadingView IsTrue="False" x:name="popupLoadingView"/>
<StackLayout>
<!-- Your collectionView goes here-->
</StackLayout>
</Grid>
</ContentPage.Content>
After doing all the pdf work, remember to turn the Visibility to false
shareTap.Tapped += (sender, e) =>
{
popupLoadingView.IsVisible = true;
//Do all the work that you need
popupLoadingView.IsVisible=false;
}
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
I am trying to create a scrollable tabs in Xamarin.Forms with CollectionView and CarouselView as specified in this link. I need to load different ContentView in CarouselView based on the Tab selected in the header.
I tried like below but the ContentView is not displaying..
Below is xaml Code:
<Grid x:DataType="{x:Null}" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="45" />
<RowDefinition Height="45" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CollectionView
x:Name="CustomTabsView"
Grid.Row="1"
HorizontalScrollBarVisibility="Never"
ItemSizingStrategy="MeasureAllItems"
ItemsSource="{Binding TabVms}"
ItemsUpdatingScrollMode="KeepItemsInView"
SelectedItem="{Binding CurrentTabVm, Mode=TwoWay}"
SelectionMode="Single"
VerticalScrollBarVisibility="Never">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3" />
</Grid.RowDefinitions>
<Label
x:Name="TitleLabel"
Grid.Row="0"
Padding="15,0"
FontAttributes="Bold"
FontSize="Small"
HeightRequest="50"
HorizontalTextAlignment="Center"
Text="{Binding Title}"
TextColor="White"
VerticalTextAlignment="Center" />
<BoxView
x:Name="ActiveIndicator"
Grid.Row="1"
BackgroundColor="Red"
IsVisible="{Binding IsSelected, Mode=TwoWay}" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never">
<CarouselView.ItemTemplate>
<DataTemplate x:DataType="local:TabViewModel">
<ContentView
x:Name="dynamiccontent"
BackgroundColor="White"
Content="{Binding DynamicContentView, Mode=TwoWay}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>
.cs file Code
private void CarouselView_CurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
{
var x = e.CurrentItem as TabItem;
var viewModel = BindingContext as xxxViewModel;
if(x.Header == Tab1)
{
viewModel.TabVms[0].DynamicContentView = new Page1();
}
if(x.Header == Tab2)
{
viewModel.TabVms[1].DynamicContentView = new Page2();
}
}
Any help is appreciated!
You could use DataTemplateSelector.
Creating a DataTemplateSelector:
class DymaicDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Tab1Template { get; set; }
public DataTemplate Tab2Template { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((TabViewModel)item).Header == "Tab1" ? Tab1Template : Tab2Template;
}
}
Consuming a DataTemplateSelector in XAML:
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="tab1Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Red"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="tab2Template" x:DataType="local:TabViewModel">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="10"
LineBreakMode="WordWrap"
Text="{Binding Content}"
TextColor="Green"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<local:DymaicDataTemplateSelector
x:Key="dymaicDataTemplateSelector"
Tab1Template="{StaticResource tab1Template}"
Tab2Template="{StaticResource tab2Template}" />
</ResourceDictionary>
</ContentPage.Resources>
Assign it to the ItemTemplate property:
<CarouselView
Grid.Row="2"
CurrentItem="{Binding CurrentTabVm, Mode=TwoWay}"
CurrentItemChanged="CarouselView_CurrentItemChanged"
HorizontalScrollBarVisibility="Never"
IsScrollAnimated="True"
IsSwipeEnabled="True"
ItemTemplate="{StaticResource dymaicDataTemplateSelector}"
ItemsSource="{Binding TabVms}"
VerticalScrollBarVisibility="Never" />
I have a mobile app with Xamarin.Forms and FreshMvvm. Every page uses a control template defined in App.xaml:
<ControlTemplate x:Key="MainPageTemplate">
<Grid BindingContext="{Binding Source={RelativeSource TemplatedParent}}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="9*" />
</Grid.RowDefinitions>
<Image Source="{local:ImageResource MyApp.Images.My_logo.jpg}" Margin="0, 0, 0, 5" Grid.Row="0" />
<Label Text="{Binding ScreenName}" FontSize="Subtitle" TextColor="Black" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1" />
<Label Text="{Binding ErrorMessage}" TextColor="Red" Grid.Row="2" />
<ContentPresenter Margin="10, 0, 10, 10" Grid.Row="3" />
</Grid>
</ControlTemplate>
The ScreenName property is defined in the PageModel like this:
protected string _screenName;
public string ScreenName => _screenName;
For some reason, the ScreenName is not showing up on the page that uses the control template. It does if I replace the Binding with a hard-coded text:
<Label Text="Something" ...
When setting your BindingContext to your {RelativeSource TemplatedParent}, your binding context is the page.
To access your ViewModel, you must change your xaml to access your property through the "BindingContext" of your page.
<Label Text="{Binding BindingContext.ScreenName}" FontSize="Subtitle" TextColor="Black" FontAttributes="Bold" HorizontalOptions="Center" Grid.Row="1" />
I have a Master-Detail Page in my project, I've set the phone language to Arabic and everything is working fine the master page is on the right and the icon is on the right. But the thing is the TitleView (toolbaritems) are pushed a little bit to the right when the phone is set to Arabic. I tried this without Master-Detail page project and the TitleView is working fine and it is in the exact place.
With Master Detail Page:
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AppXamarin.Pages"
x:Class="AppXamarin.Pages.MasterMainPage" NavigationPage.HasNavigationBar="False" NavigationPage.HasBackButton="False" FlowDirection="{x:Static Device.FlowDirection}">
<MasterDetailPage.Master>
<local:MasterPage x:Name ="masterPage" FlowDirection="{x:Static Device.FlowDirection}"/>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage FlowDirection="{x:Static Device.FlowDirection}">
<x:Arguments>
<local:MenuPage></local:MenuPage>
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
MenuPage Xaml file:
<NavigationPage.TitleView>
<Grid Grid.Row="0" Grid.Column="0" HorizontalOptions="EndAndExpand" FlowDirection="{x:Static Device.FlowDirection}">
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="cart_Clicked"/>
</Grid.GestureRecognizers>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image x:Name="BadgeIconImage" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" Margin="6" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Source="cart">
<Image.HeightRequest>
<OnIdiom Phone="25" Tablet="35"/>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom Phone="25" Tablet="35"/>
</Image.WidthRequest>
</Image>
<Frame x:Name="BadgeFrame" Grid.Row="0" Grid.Column="1" CornerRadius="12" Padding="10,4" HasShadow="false" OutlineColor="Transparent" BackgroundColor="Transparent">
<Label x:Name="BadgeTextLabel" FontSize="12" FontAttributes="Bold" HorizontalOptions="EndAndExpand" TextColor="#FF0000"/>
</Frame>
</Grid>
</NavigationPage.TitleView>
Result:
Without Master Detail Page:
<NavigationPage.TitleView>
<Grid Grid.Row="0" Grid.Column="0" HorizontalOptions="EndAndExpand" FlowDirection="{x:Static Device.FlowDirection}">
<!--<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="cart_Clicked"/>
</Grid.GestureRecognizers>-->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image x:Name="BadgeIconImage" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" Margin="6" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Source="cart">
<Image.HeightRequest>
<OnIdiom Phone="25" Tablet="35"/>
</Image.HeightRequest>
<Image.WidthRequest>
<OnIdiom Phone="25" Tablet="35"/>
</Image.WidthRequest>
</Image>
<Frame x:Name="BadgeFrame" Grid.Row="0" Grid.Column="1" CornerRadius="12" Padding="10,4" HasShadow="false" OutlineColor="Transparent" BackgroundColor="Transparent">
<Label x:Name="BadgeTextLabel" FontSize="12" FontAttributes="Bold" HorizontalOptions="EndAndExpand" TextColor="#FF0000"/>
</Frame>
</Grid>
<!--</Grid>-->
</NavigationPage.TitleView>
Result:
My understanding tells me you are trying to add toolbar items so you do not use titleView for that:
What you should be doing, on the other hand, is something like below
C#:
this.ToolbarItems.Add(new ToolbarItem()
{
Icon = "BadgeIconImage",
Command = YourCommand,
});
XAML:
<ContentPage.ToolbarItems>
<ToolbarItem Order="Primary" Icon="BadgeIconImage" />
</ContentPage.ToolbarItems>
To understand Xamarin Forms Toolbar check this guide by Adam Pedley
Update
I have a feeling that the padding that you are using on the Frame is what's pushing your View
Padding="10,4"
Check this:
<Frame x:Name="BadgeFrame" Grid.Row="0" Grid.Column="1" CornerRadius="12" Padding="10,4" HasShadow="false" OutlineColor="Transparent" BackgroundColor="Transparent">
Also could be the corner radius.
Yes I did it
manifest :
<application android:label="Sanaap" android:icon="#mipmap/launcher_foreground" android:theme="#style/MainTheme" android:supportsRtl="true">
MainView.xaml
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Sanaap.App.Views.MenuView"
FlowDirection="RightToLeft"
Title="Main">