How to put usercontrol in itemsControl in wpf prism - prism

I want to insert user control to itemscontrol in wpf using prism.
The user control is printed, but I don't know how to do data binding.
ViewA.xaml
<Grid>
<ItemsControl ItemsSource="{Binding People}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Grid.Row="1" Margin="10"
prism:RegionManager.RegionName="PersonDetailsRegion"
prism:RegionManager.RegionContext="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
ViewAViewModel.cs
private ObservableCollection<Person> _people;
public ObservableCollection<Person> People
{
get { return _people; }
set { SetProperty(ref _people, value); }
}
public ViewAViewModel()
{
CreatePeople();
}
private void CreatePeople()
{
var people = new ObservableCollection<Person>();
for (int i = 0; i < 10; i++)
{
people.Add(new Person()
{
FirstName = String.Format("First {0}", i),
LastName = String.Format("Last {0}", i),
Age = i
});
}
People = people;
}
insert a menu item into viewA.
MenuItem.xaml
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- First Name -->
<TextBlock Text="First Name:" Margin="5" />
<TextBlock Grid.Column="1" Margin="5" Text="{Binding FirstName}" />
<!-- Last Name -->
<TextBlock Grid.Row="1" Text="Last Name:" Margin="5" />
<TextBlock Grid.Row="1" Grid.Column="1" Margin="5" Text="{Binding LastName}" />
<!-- Age -->
<TextBlock Grid.Row="2" Text="Age:" Margin="5"/>
<TextBlock Grid.Row="2" Grid.Column="1" Margin="5" Text="{Binding Age}"/>
</Grid>
![The current situation is as follows.][1]
https://i.stack.imgur.com/1VBai.png
How to do data binding? please help me
thanks you

This won't work like this. You have to create the region on the "outside", i.e. on the ItemsControl and remove the ItemsSource binding. Then navigate multiple times to the items control-region to populate it.
<ItemsControl prism:RegionManager.RegionName="PersonDetailsRegion"/>
Alternatively, keep the binding of ItemsSource and remove the ContentControl inside and put DataTemplates somewhere for your views. Then populate it by putting the view models into the items source.
<DataTemplate DataType={x:Type Person}"><PersonView /></DataTemplate>
...
<ItemsControl ItemsSource="{Binding People}"/>
Personally, I'd prefer the second variant most of the time, because you evade the added complexity of packing your persons' information in navigation parameters and getting them back, not to speak of the much simpler PersonViewModel...

Related

CollectionView Xamarin How to speed rendering

I have a list to show where we show repeat information from SQlite database to user. In this we show basically the product price, name and type. Usually a user will have 10-15 of such records.
Problem is it take 10+ sec to display the list. Now, the architecture of application. On page load of Shell application we fetch the information from web request and store that in SQlite and then Bind the Result from Sqlite StackLayout with Bindable Property. But it took more than 10-11 Sec to display us.
So we change it to Grid with Bindable property and results are same. Though I don't like CollectionView (as I found their select property weird. ) We use CollectionView with dataTemplate as Grid (as we have some tabular information to show) . The results still take same 10+ secs to load up.
i.e. I use Stacklayout, Grid, CollectionView, it take that much time. We are not using the ObservableCollection to bind, but our class elements are all INotifyPropertyChanged. So, I try to disable it but still even when I do not inherity INotifyPropertyChanged and remove "OnPropertyChanged" calls it still take same time.
However, when I reduce the information to just show the name of product (through binding) it reduce to 5 secs. Which is still a lot as a Collection View with just 10 records and showing one Bindable Grid showing result in 5 second is lot more than expected. I understand my other data (which call functions) maybe slowing it down but can we reduce those 5 second somehow?
I cannot share much of class, but some of properties are pretty straight forward Property with INotifyPropertyChange on string or int values.
Here is Code for loading CollectionView
public async Task LoadSearch()
{
CurrentState = LayoutState.Loading;
try
{
var o = await PatientMedicine.FetchPatientMedicine();
if (o)
{
var _sr = (await DBCoreAsync.GetDataAsync<PatientMedicine>())?.OrderBy(x => x.PatientMedID).ToList();
if (_sr != null)
{
SearchResults = _sr;
}
CurrentState = LayoutState.Success;
}
else
{
CurrentState = LayoutState.Error;
}
}
catch (Exception ex)
{
CurrentState = LayoutState.Error;
}
}
Here is Collection itself.
<CollectionView ItemsSource="{Binding SearchResults}" ItemSizingStrategy="MeasureFirstItem">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="0,7" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView BackgroundColor="{Binding LowStock, Converter={StaticResource BoolToColorReverse}}" CornerRadius="5,0,5,0" />
<Grid Grid.Column="1" Margin="0"
Padding="10,5" BackgroundColor="{StaticResource PrimaryLight2}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.Column="0" Grid.Row="0" Source="{Binding Medicine.RxIcon}" ></Image>
<Label Grid.Column ="1" Grid.Row="0" Style="{StaticResource GeneralLabelBlack}" Text="{Binding Medicine.MedicineName}"></Label>
<Button Grid.Column="2" Grid.Row="0" Command="{Binding Path=BindingContext.NavigateToMedicineReminder, Source={x:Reference Name=MedicineListPageName}}" CommandParameter="{Binding .}"
BackgroundColor="Transparent" VerticalOptions="Center" HorizontalOptions="End" ImageSource="{FontImage FontFamily=FontAwesomeSolid, Glyph=, Color={StaticResource Primary},Size=16}" ></Button>
<Image Grid.Column="0" Grid.Row="1"
Source="{StaticResource ImageSourceIconClockOpenHand}"></Image>
<Label Grid.Column ="1" Grid.Row="1" Text="{Binding RepeatStatusFormatted}"></Label>
<Image Grid.Column="0" Grid.Row="2"
Source="{StaticResource ImageSourceIconStock}"></Image>
<Label Grid.Column ="1" Grid.Row="2" Text="{Binding StockAndRequirement}"></Label>
<Image Grid.Column="0" Grid.Row="3"
Source="{StaticResource ImageSourceIconClock}"></Image>
<Label Grid.Column ="1" Grid.Row="3" Text="{Binding NextReminder}"></Label>
<Label Grid.Column ="0" Grid.Row="4" Grid.ColumnSpan="2" Text="{Binding Medicine.AilmentString}"></Label>
<Label Grid.Column ="0" Grid.ColumnSpan="2" Grid.Row="5" IsVisible="{Binding LowStock}" Text="Stock running low. Order a refill now" HorizontalOptions="End"></Label>
<Button Grid.Column="2" Grid.Row="5" Command="{Binding Path=BindingContext.AddtoCart, Source={x:Reference Name=MedicineListPageName}}" CommandParameter="{Binding .}"
BackgroundColor="Transparent" IsVisible="{Binding LowStock}" VerticalOptions="Center" HorizontalOptions="End" ImageSource="{FontImage FontFamily=FontAwesomeSolid, Glyph=, Color={StaticResource Primary},Size=16}" />
</Grid>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
To add more information: I am okay with Internet load time which is <=1.5 seconds the time I calculate and show here is exclusively for When I set the ViewModel to Values from temporary variable to main variable I did it just to see if DB access is slow or not. (to step it out). I have my control inside a StackLayout that use Xamarin Community Toolkit statelayout.
Also I go through MS's Suggestion on optimizing performance about Compile XAML etc, but since it is new App using Xamarin Forms 5.0 I don't think it is problem as it is already set by default.

Xamarin Forms CollectionView TapGestureRecognizer not firing on label

I have a XF app with the following collection view defined. The 2nd label has a TapGestureRecognizer that doesn't fire DoSomethingInteresting in the model when I tap the label (trying this on Android). Can someone see what the issue is please?
A working sample can be cloned from here.
XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SampleApp"
x:Class="SampleApp.MainPage">
<StackLayout>
<CollectionView ItemsSource="{Binding GaugeSites}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Label Grid.Column="0"
Text="{Binding Description}"
FontSize="20"
Margin="10"
TextColor="Black"
FontAttributes="Bold" />
<Label Grid.Column="1"
Margin="10"
FontSize="20"
Text="Click Me!">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding DoSomethingInteresting}" />
</Label.GestureRecognizers>
</Label>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
Model
namespace SampleApp
{
public class MainPageModel : FreshBasePageModel
{
public MainPageModel() : base()
{
GaugeSites = new List<GaugeSite>();
for (var index = 1; index <= 5; index++)
{
GaugeSites.Add(new GaugeSite()
{
Description = $"Gauge Site {index}"
});
}
}
public List<GaugeSite> GaugeSites { get; set; }
public Command DoSomethingInteresting
{
get
{
return new Command(() =>
{
});
}
}
}
[AddINotifyPropertyChangedInterface]
public class GaugeSite
{
public string Description { get; set; }
}
}
Maybe this is redundant but I will take my chances. As other answers indicated you need to set the source within your TapGestureRecognizer to the name of the CollectionView. However, it is probably useful to know which GaugeSite instance was associated with the CollectionView item whose TabGestureRecognizer was tapped. To add this info add a CommandParamter, i.e.
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.DoSomethingInteresting,
CommandParameter="{Binding}"
Source={x:Reference YourCollectionName}}" />
</Label.GestureRecognizers>
When it comes to the command you could use
DoSomethingInteresting = new Command<GaugeSite>((a) => DoSomething(a));
in your viewmodels contructor. And the method referenced by the lambda would be
void DoSomething(GaugeSite gaugeSite)
{
// ....
}
Hope this helps
I have download your sample, please take a look the following step.
1.Binding MainpageModel for MainPage bindingContext, add this line in MainPage.cs.
this.BindingContext = new MainPageModel();
2.Name Collectionview as collection1, then modify label command.
<CollectionView x:Name="collection1" ItemsSource="{Binding GaugeSites}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Label
Grid.Column="0"
Margin="10"
FontAttributes="Bold"
FontSize="20"
Text="{Binding Description}"
TextColor="Black" />
<Label
Grid.Column="1"
Margin="10"
FontSize="20"
Text="Click Me!">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.DoSomethingInteresting, Source={x:Reference collection1}}" />
</Label.GestureRecognizers>
</Label>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Then you can try again.

Can't bind ListView to ViewModel

This my ViewModel:
namespace DietAndFitness.ViewModels
{
public class FoodItemsViewModel
{
private SQLiteAsyncConnection database;
public static ObservableCollection<GlobalFoodItem> FoodItems { get; set; }
public FoodItemsViewModel(SQLiteAsyncConnection _database)
{
database = _database;
}
public async void LoadList()
{
FoodItems = new ObservableCollection<GlobalFoodItem>(await database.Table<GlobalFoodItem>().ToListAsync());
}
public void Add()
{
FoodItems.Add(new GlobalFoodItem("Item"));
}
}
}
I want to bind an instance of this VM to the list in my View but I just can't get it to work properly. The only thing I've managed to get to work is this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DietAndFitness.ViewModels"
x:Class="DietAndFitness.Views.FoodDatabasePage">
<ContentPage.Content>
<StackLayout>
<ListView ItemsSource="{Binding FoodItems}" RowHeight="120">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Padding="5">
<Frame OutlineColor="Accent" Padding="10">
<StackLayout>
<Grid HorizontalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" FontSize="22" VerticalOptions="CenterAndExpand" HorizontalOptions="Center" Grid.Row="0" Grid.Column="0"/>
<Label Text="{Binding Calories}" FontSize="22" VerticalOptions="CenterAndExpand" HorizontalOptions="Center" Grid.Row="0" Grid.Column="1"/>
</Grid>
<Grid HorizontalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Text="Carbohydrates" Grid.Row="1" Grid.Column="0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="16"/>
<Label Text="Proteins" Grid.Row="1" Grid.Column="1" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="16"/>
<Label Text="Fats" Grid.Row="1" Grid.Column="2" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="16"/>
<Label Text="{Binding Carbohydrates}" Grid.Row="2" Grid.Column="0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="16"/>
<Label Text="{Binding Proteins}" Grid.Row="2" Grid.Column="1" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="16"/>
<Label Text="{Binding Fats}" Grid.Row="2" Grid.Column="2" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" FontSize="16"/>
</Grid>
</StackLayout>
</Frame>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Grid HorizontalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="AddFoodItemButton" BackgroundColor="LightGray" HorizontalOptions="CenterAndExpand" Text="Add" Grid.Row="0" Grid.Column="0" Clicked="AddFoodItemButton_Clicked" />
<Button x:Name="EditFoodItemButton" BackgroundColor="LightGray" HorizontalOptions="CenterAndExpand" Text="Edit" Grid.Row="0" Grid.Column="1" />
<Button x:Name="DeleteFoodItemButton" BackgroundColor="LightGray" HorizontalOptions="CenterAndExpand" Text="Delete" Grid.Row="0" Grid.Column="2" />
</Grid>
</StackLayout>
</ContentPage.Content>
But this has problems too:
If I create the VM in the page constructor the list won't load unless I refresh the page
If I create the VM inside App.cs the list will load on the first try but then I can't seem to access the instance of the VM
How do I bind my ListView to this VM? And is it possible to do so without making my ObservableCollection static?
I'm using a Master-Detail page in my app if it makes any difference (this is one of the detail pages).
Edit: Here is what I did in the constructor. SQLiteConnection.Database is just a static class that contains the connection to the database.
public FoodDatabasePage ()
{
FoodDatabase = new FoodItemsViewModel(SQLiteConnection.Database);
FoodDatabase.LoadList();
InitializeComponent ();
}
There's a few things that you have there.
When binding a ViewModel usually it's against the whole Page making the ViewModel its BindingContext specially in cases like yours when you have methods that want to access later.
So to do this you will need a few changes.
Your Page XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DietAndFitness.ViewModels"
x:Class="DietAndFitness.Views.FoodDatabasePage">
<ContentPage.Content>
<StackLayout>
<ListView ItemsSource="{Binding FoodItems}"
RowHeight="120">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame OutlineColor="Accent" Padding="15">
<StackLayout>
<Grid HorizontalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}"
FontSize="22"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Grid.Row="0"
Grid.Column="0"/>
</Grid>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Check that I changed the ListView ItemSource for the name of the collection in your FoodItemsViewModel.
Also, part of your XAML disappeared so I could not complete it.
Your Code Behind class: (FoodDatabasePage.xaml.cs)
public FoodItemsViewModel FoodDatabase {get; set;}
public FoodDatabasePage ()
{
InitializeComponent ();
FoodDatabase = new FoodItemsViewModel(SQLiteConnection.Database);
BindingContext = FoodDatabase;
}
public override void OnAppearing()
{
FoodDatabase.LoadList();
}
Here is where the "magic" happens. We are creating and storing the object of our FoodItemsViewModel so you can access it later as you need and then we are setting this object recently created as the BindingContext of the page (as explained above). Setting the ViewModel as the BindingContext of Page the latter will be able to access any public property of the FoodItemsViewModel.
Also, you will notice the LoadList() method was removed from the constructor, this is because there shouldn't be any heavy transaction (actually we should avoid any transactions) in the Page constructor. We moved it instead to the OnAppearing callback method that is executed by the Page when this is about to be displayed.
Note: This method is called every time the Page is presented on the screen so if you navigate away and come back it will be called again.
Your ViewModel:
namespace DietAndFitness.ViewModels
{
public class FoodItemsViewModel
{
private SQLiteAsyncConnection database;
//You don't need it static
public ObservableCollection<GlobalFoodItem> FoodItems { get; set; }
public FoodItemsViewModel(SQLiteAsyncConnection _database)
{
database = _database;
}
public async void LoadList()
{
// separated it only for readability.
var items = await database.Table<GlobalFoodItem>().ToListAsync();
FoodItems = new ObservableCollection<GlobalFoodItem>(items);
}
public void Add()
{
FoodItems.Add(new GlobalFoodItem("Item"));
}
}
}
This remains almost the same. The only change was removing the static qualifier to the FoodItems property since it does not need it anymore.
The above is just the basic of Mvvm and DataBinding. There're a few other things that you will need to take into consideration like INotifiedPropertyChanged, Commands and other important things.
You can find more information regarding this here
Hope this helps.-
PS: I couldn't check all of your code for any error.

Xamarin resize Listview item-height based on viewcell width

My goal is to have a listview with a resizeable icon on the left, and 3 lines of text in the other column. Here is the template I've tested so far:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Margin="0,0" Padding="0,0" ColumnSpacing="0" RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="85*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Grid.Column="0" Source="{Binding sImageSource}" Aspect="AspectFit" />
<StackLayout Grid.Row="0" Grid.Column="1" Orientation="Vertical" Margin="0" Padding="0" Spacing="0">
<Label Text="{Binding sDisplayName}" FontSize="Medium" LineBreakMode="TailTruncation" YAlign="Center" TextColor="Black"/>
<Label Text="{Binding sFileSize}" FontSize="Micro" TextColor="Gray" YAlign="Center"/>
<Label Text="{Binding sFileDate}" FontSize="Micro" TextColor="Gray" YAlign="Center"/>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
If the ColumnDefinition Width="15*" is changed to "25*" I just get a wider column, and the picture is not changed in height (As I though it would).
Actually what I want is that RowDefinition Height="ColumnDefinition Width="15*"", so the both resize linear based on the parameter set as width.
Does anyone have tips regarding this?
PS: I have also tested HasUnevenRows=True, but that sets the height of each cell too high.
Edit:
Another variation has been tested:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" x:Name="MyImageGrid"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition BindingContext="{x:Reference MyImageGrid}" Height="{Binding Path=ActualWidth}"/>
</Grid.RowDefinitions>
But that did not work either. Have anyone done such a solution before?
I sort-of solved this little nut, but it was more complicated than it should be.
Here is the solution if anyone wonders.
In your contentpage-csfile, you have to add an property to store the value needed
public partial class YourPage : ContentPage
{
//....
public class RowHeight : INotifyPropertyChanged
{
private int nInternalHeight;
public event PropertyChangedEventHandler PropertyChanged;
public int Height
{
get { return nInternalHeight; }
set
{
nInternalHeight = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Height"));
}
}
}
//....
public RowHeight oRowHeight { get; set; }
//....
public YourPage()
{
oRowHeight = new RowHeight();
}
//....
protected override void OnAppearing()
{
base.OnAppearing(); //Width is -1 if set right away in YourPage() creation
oRowHeight.Height = (int)(App.Current.MainPage.Width * 0.15);
}
//....
Now in the XAML part of the code.
Our object oRowHeight.Height needs to be bound to our RowDefinition Height property.
The ListView also must have the following criterias:
1. HasUnevenRows = True
2. Page has to have a name for the reference
<?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="YourApp.Views.YourPage"
x:Name="YourPageName">
<ContentPage.Content>
<StackLayout>
<ListView ItemsSource="{Binding OtherItems}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Margin="0,0" Padding="0,0" ColumnSpacing="0" RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="85*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding Source={x:Reference YourPageName}, Path=BindingContext.oRowHeight.Height}" />
</Grid.RowDefinitions>
<!-- Like the rest of XAML above -->

Binding list Collection from a list collection in Window Phone 7

How to Binding list Collection from a list collection in Window Phone 7 while i am able to bind from a single list collection
First of all have item template in your Xaml.
Add Binding to it.
Define that binding property in your code.
Assign values to the defined property.
I am having a item template in my Xaml like this :
<Grid.RowDefinitions>
<RowDefinition Height="367*" />
</Grid.RowDefinitions>
<ListBox HorizontalAlignment="Stretch" Name="lstbNewOrders" Grid.Row="1" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="itemTemplate" Background="Transparent" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<TextBlock FontSize="30" Name="txtEbeln" Text="{Binding ebeln}" Grid.Row="0" Grid.Column="0" FontWeight="Bold" />
<TextBlock FontSize="25" Name="txtCName" Text="{Binding cname}" Grid.Row="1" Grid.Column="0" />
<TextBlock FontSize="25" Name="txtDate" Text="{Binding date}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" TextAlignment="Right"/>
<StackPanel Height="30" Name="stkPanel01" HorizontalAlignment="Right" Grid.Row="0" Grid.Column="1">
<TextBlock FontSize="25" Name="txtNetw" Text="{Binding netw}" HorizontalAlignment="Right" TextAlignment="Right"/>
</StackPanel>
<TextBlock FontSize="25" Name="txtVName" Text="{Binding vname}" Grid.Row="2" Grid.Column="0" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
In my code file i will define the binding like this:
public class itemListForListBox
{
public string ebeln { get; set; }
public string cname { get; set; }
public string vname { get; set; }
public string netw { get; set; }
public string date { get; set; }
}
And provide values like this:
void fillList()
{
List<itemListForListBox> itemListbox = new List<itemListForListBox>();
itemListForListBox listItem;
for (int i = 0; i < 5;i++ )
{
listItem = new itemListForListBox();
listItem.ebeln = "Name "+i;
listItem.date = "Date "+i;
listItem.vname = "VName "+i;
listItem.netw = "Amount "+ i;
listItem.cname = "CName "+i;
itemListbox.Add(listItem);
}
lstbNewOrders.ItemsSource = itemListbox;
}
Hope this might help you.
Thanks.
You can use the code below,
<ListBox Name="RouteListBox" ItemContainerStyle="{StaticResource RouteListBoxItemStyle}" SelectedItem="{Binding Model.SelectedRoute,Mode=TwoWay}" ItemsSource="{Binding RouteListCollection}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<command:EventToCommand Command="{Binding RouteItemSelectedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding RouteName}" Style="{StaticResource RoutesStyle}" Grid.Column="1" />
<Border Style="{StaticResource RouteCountBorder}" Visibility="Collapsed" Grid.Column="2">
<TextBlock Style="{StaticResource RoutesCount}" Visibility="Collapsed" Text="{Binding ShopCount,Mode=TwoWay}"></TextBlock>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate></ListBox>
I take it you mean you have a collection of collections? In this case, you can nest your ItemsControls (or ListBox):
<ItemsControl ItemsSource={Binding Path=???}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- here is your nested itemscontrol -->
<ItemsControl ItemsSource={Binding Path=???}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- your content goes here -->
</DataTemplate>
<ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Let say we have a ListBox lstbx and a collection lets say
List <String> listdata = new List<String>();
we can add items to the collection by Add()
Ex-
listdata.Add("Nazi 1");
or
forloop(expression)
{
listdata.Add("vale")
}
then we can assign assign the collection directly to the listbox' item Source
ex.
lstbx.ItemSource=listdata;
//make sure if u are storing more than one variable in a single item of the collection ,you should create custom data template for the ListBox Item Template. !

Resources