I have a question. I created a TabbedPage with 2 childs. In child1 I want to show the selected images. In child2 I have a Grid with a few images. Now I want to make the images in child2 selectable and when they get clicked, I want them to be inserted in the StackLayout in child1. I have no clue how to start, so can someone give me an example?
Here is the xaml from child1:
<ContentPage.Content>
<StackLayout BackgroundColor="White" x:Name="MainLayout" VerticalOptions="Center">
</StackLayout>
</ContentPage.Content>
Here is the Grid from child2
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<Image Grid.Row="1" Grid.Column="1" Source="Good_Question.png" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" />
<Image Grid.Row="1" Grid.Column="3" Source="Excuse_Me.png" />
</Grid>
Can someone give me an example of how I can add an Image that is selected in a different tab to another tab in a TabbedPage?
There are multiple ways to do so:
1 way(Simple):
Create a public static ObservableCollection<Image> imageCollection= new ObservableCollection<Image>(); on main page.
Then On Page2 : Add the selected images inside imageCollection .
On Page1: Add imageCollection.CollectionChanged += AddImageInsdeFirstPageLayout();.
CollectionChanged is call whenever any element is added/removed inside ObservableCollection.
2nd way(Work throuh MVVM logic & Preferred way):
Create a common ViewModel for all three pages(main Page & tabbed Pages).
Create a property inside it,namely,
public ObservableCollection<Image> _selectedImages { get; set; }
public ObservableCollection<Image> SelectedImages
{
get { return _selectedImages; }
set
{
_selectedImages = value;
OnPropertyChanged();
}
}
Add new elements inside this property from Page2 and access this property from Page1.
Make sure, you raise OnPropertyChanged
3rd way(i don't like this):
Use MessagingCenter. It's pretty simple to use.Go through this,if you want to dig more: Xamarin.Forms MessageCnter
My suggestion is use a tabbed view instead of tabbed pages https://help.syncfusion.com/xamarin/tabbed-view/getting-started .
Use Two ListViews in both Child Tabs, and when the Second Child tab's image is selected, get the selected item from ItemSelectedEvent and bind it to the First Child tab's listview. And if you need, you can removed the selected item from Second Tab's ListView.
AS both listviews in same page you dont have to worry about passing data between pages.
you can use a MessageCenter to translate the Image Source.
google the Xamarin api to add it then all will be ok.
Related
I have a List object called mylist that contains a list of strings that represent names stored in a database. I want to display this list in a collection view. So far, i've been able to set the collection view itemsource property to mylist, which works fine. when i do this, it shows me the list in the default mode for collection view which is a vertical list. Now, i want to actually apply some formatting to the list by putting it inside of a grid and making it look nice. This is where my issue is. All of the examples on microsoft documentation set the Binding of the collection view to some class, and then they set the binding for the views in the list to the properties of that class. The issue with that for me is that I am not using the MVVM architecture. I am not setting the binding to a class. I want to set it directly to a list object. This is what i have so far for my xaml
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0"
Grid.Column="0"
Text=**WHAT DO I PUT HERE**
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="0"
Text=**WHAT DO I PUT HERE**
/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
...
</CollectionView>
and from my code behind file here is the relevant snippet
```Collection.Itemsource = mylist;
```
As you can see, i want to display the data that is in my list string in the text of the labels i have created. but i don't know how to reference that data. I've already tried mylist[0] but that doesn't work
if your ItemSource is a List<string>
Text=**WHAT DO I PUT HERE**
should be
Text="{Binding .}"
. tells it to use the value of the object itself, not a property of the object
How to customize the WindowChrome class while using MvvmCross?
I've got this:
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="{x:Static SystemParameters.CaptionHeight}" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
FontSize="32"
Text="SOME UPPER CASE TEXT THAT WILL NEVER BE DISPLAYED" />
</Grid>
inside my MvxWindow and the WindowStyle is set to none.
The problem is that MvxWindow doesn't seem to display anything. That means I can't create the buttons I need either. I don't know if MvvmCross expects every UI element to be part of a View or what else is going on. Resizing and even right-clicking the invisible border works just fine. Is there any way to do this without having to rebuild the entire WindowChrome functionality inside a View?
I will answer this myself;
while there is little difference in creating a custom WindowChrome with MvvmCross, I'll keep this question up in the hope that it could help someone else.
Not being able to display UI elements in MvxWindow is actually no problem at all. Just create the UI in your View and set the WindowChrome.IsHitTestVisibleInChrome property to true for each element you need.
There is basically no difference between doing this within a Window or a View. You just have to keep an eye on your CaptionHeight as your WindowChrome and your UI are now in two different scripts.
It could look like this:
Inside your MvxWindow:
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="{x:Static SystemParameters.CaptionHeight}" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
Inside the view displayed by that window:
<Menu Height="{x:Static SystemParameters.WindowCaptionHeight}">
<MenuItem Header="_Exit" WindowChrome.IsHitTestVisibleInChrome="True" />
</Menu>
I'm trying to add a grid view at the bottom of the screen containing 'Current Playing' information about a media being played in a media player. The problem is that I want this view to be there no matter what is the page visible.
The main layout is a Master-Detail page for the navigation menu panel, where the detail page should contain everything.
The detail page can be a content page, a navigation page (mostly) or a modal content page. However, if I might only choose one, I would choose it to be a navigation page.
So, simply I want to do something like this:
<MasterDetailPage.Detail>
<ContentPage>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Page x:Name="viewPort" Grid.Row="0">
<!--This page source is dynamically set from the code behind...-->
</Page>
<Grid Grid.Row="2">
<!--Here should be the rest of my grid structure...-->
</Grid>
</Grid>
</ContentPage>
</MasterDetailPage.Detail>
But wrapping a page inside another view/page is not possible, I tried also modifying the Master-Detail page control template to add that grid at the bottom of the detail page and display whatever page above it, but no luck in finding the original template or even setting a template for Master-Detail layout...
I'm new to Xamarin but somewhat experienced with c# and xaml, any help is really appreciated.
You could use ContentPresenter with control template.
Create a control template in App.xaml> Application.Resources> ResourceDictionary.
<!-- Grid Template -->
<ControlTemplate x:Key="GridTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" />
<Label
Grid.Row="1"
BackgroundColor="Accent"
Text="Grid Template" />
</Grid>
</ControlTemplate>
And then use it in detail page.
ControlTemplate="{StaticResource GridTemplate}"
I have uploaded the project on GitHub for your reference.
https://github.com/WendyZang/Test/tree/master/ControlTemplate_ContentPresenter/MasterDetailPageDemo
Updated:
For data binding of control template, you could use TemplateBinding.
Create a AppViewModel:
public class AppViewModel
{
public string Name { get; set; } = "Name_A";
public AppViewModel()
{
}
}
App.xml:
<ControlTemplate x:Key="GridTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" />
<Label Grid.Row="1" BackgroundColor="Accent" Text="{TemplateBinding BindingContext.Name}" />
</Grid>
</ControlTemplate>
Set the binding in each page which use the control template.
this.BindingContext = new AppViewModel();
View Image here..See section circled with black ink l want to add a second row to the Collection view in my project. This second row is suppose to be horizontal list the first one and consist of different images
l have tried adding another image tag to the collection view template but it does solve my problem as it repeats the same images twice. Find my code below
<CollectionView ItemsSource="{Binding sliders}"
HorizontalOptions="CenterAndExpand" HeightRequest="150" >
<CollectionView.ItemsLayout>
<ListItemsLayout>
<x:Arguments>
<ItemsLayoutOrientation>Horizontal</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid BackgroundColor="#282626" Padding="0,5,0,0" >
<Grid.RowDefinitions >
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Url}"
Aspect="AspectFill"
HeightRequest="160"
WidthRequest="160"
Grid.Row="0"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"/>
<Label Text="{Binding Name}" TextColor="White" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The code above adds a collections view with one row to the project.
Kindly help me add a second row with different images.
The CollectionView element displays one row per object in your Source (in this case, "sliders"). So, in order to create another row, you have to simply add another object to your "sliders" list with the image you want to be displayed in the second row.
Adding another Image to the DataTemplate will not work because it will be referencing the same object, and if you're using the same property as the image source (in this case, "Url"), it will display the same image.
So I am currently working on my first Xamarin application.
I have a MasterDetailPage with a menu, and when you click on one of the menu items on the left the below I save the object I am working with (to the file system), I create a new 'ContentPage' for the page they have chosen and pass in the object as a constructor parameter.
I then attempt to set the MasterDetailPage Detail object to (ContentPage)obj which is a cast of the content page they have chosen.
Now as you can see, the base for the JobDetails is a ContentPage, yet I cannot cast it to content page!?
I have also tried casting to Page instead to no avail.
Am I missing some fundamental knowledge when it comes to casting, or is something else going on here?
I have solved this.
The issue wasn't with the Content Page cast (casting from obj > content page) but was because I had some xaml which wasn't correct inside JobDetails page.
The offending xaml was a
<ListView Grid.Row="3" Grid.ColumnSpan="2" Grid.Column="0" x:Name="KeySkillsList">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding Name, Mode=TwoWay}"></Label>
<Switch Grid.Row="0" Grid.Column="1" IsToggled="{Binding Value, Mode=TwoWay}"></Switch>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This was due to me misunderstanding the list view (and the switch!)
The actual offending line specifically was the , commented out the page works.
I have now changed this so that its just a normal list view, with 1 switchcell, with a Text property.