Contact Number repeating in Xamarin.forms - xaml

I am facing a issue while retrieving contact list from the phone i am getting same contact number for all contact names in Xamarin.Forms. I am new in Xamarin and want to load all phone contacts in listview.
Here is my Code:
private List<ContactMenu> LoadAllContacts()
{
List<ContactMenu> getContactNamesAndNumber = new List<ContactMenu>();
//Bind Contacts
var forContactNames = ContactsContract.Contacts.ContentUri;
string[] forContactNumbers = {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName
};
var forContactNumber = ContactsContract.CommonDataKinds.Phone.ContentUri;
string[] forContactDisplayNumber = { ContactsContract.Contacts.InterfaceConsts.Id, ContactsContract.CommonDataKinds.Phone.Number };
var names = ManagedQuery(forContactNames, forContactNumbers, null, null, null);
var nameList = new List<string>();
var number = ManagedQuery(forContactNumber, forContactDisplayNumber, null, null, null);
var numbeList = new List<string>();
if (names.MoveToFirst() && number.MoveToFirst())
{
do
{
getContactNamesAndNumber.Add(new ContactMenu
{
ContactName = names.GetString(names.GetColumnIndex(forContactNumbers[1])), ContactNumber = number.GetString(number.GetColumnIndex(forContactDisplayNumber[1]))
});
numbeList.Add(number.GetString(number.GetColumnIndex(forContactDisplayNumber[1])));
nameList.Add(names.GetString(names.GetColumnIndex(forContactNumbers[1])));
} while (names.MoveToNext());
}
ListAdapter = new ArrayAdapter<string>(this, Resource.Layout.ContactItemView, numbeList);
return getContactNamesAndNumber;
}
And My Xaml :
<StackLayout HorizontalOptions="Center">
<Label Text="Please Select Contact" TextColor="Black" FontFamily="Arial" FontSize="Medium" Font="16"></Label>
<ListView x:Name="myContacts" HorizontalOptions="Start" ItemTapped="myContacts_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding ContactName}" DetailColor="Green" TextColor="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>

You have two ManagedQuerys, names and number but are only advancing the names query via names.MoveToNext() at the end of your do loop.
You should remove one of the ManagedQuery and return all the columns that you need in just one query so you can obtain the name and matching number from the same data row.

Related

XAML small Multicolumn List inside LiesView Element

In my Xamarin App I have a ListView, inside the ItemTemplate I have to show a text-only list with 3 columns.
The first idea was to use a GroupedListView, but in this case all subentries are selectable separately.
That is not what I want. The ListView Item should appear as one selectable element.
The Second idea I found on my research is to add Gridview rows by code, but this would break my MVVM concept. I need a solution which works with databinding only.
The third thing I sometimes read is: cascade a ListView inside the ListView. But mostly the answer to such idea is: "never do this".
Any other idea what I can do for this?
What I want is something like this:
ListView Entry 1
04:13 Jhonny 3,24$
09:45 Some Long Nam... 8,23$
14:42 Mike 5,45$
----------------------------------------
ListView Entry 2
07:13 Jhonny 3,24$
11:22 Some Long Nam... 8,23$
18:42 Mike 5,45$
----------------------------------------
ListView Entry 3
05:13 Jhonny 3,24$
15:45 Some Long Nam... 8,23$
19:42 Mike 5,45$
----------------------------------------
Always the whole Listview Entry should be selectable as one element.
Guess you could use the BindableLayout. You didn't specify the Type, so i made a dummy type.
View:
<CollectionView ItemsSource="{Binding GroupItems}" SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Vertical" Margin="5">
<Label Text="{Binding Title}"/>
<StackLayout BindableLayout.ItemsSource="{Binding Entries}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Time}" HorizontalTextAlignment="Center"/>
<Label Text="{Binding Name}" Grid.Column="1" LineBreakMode="TailTruncation"/>
<Label Text="{Binding Amount}" Grid.Column="2" HorizontalTextAlignment="Center"/>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Codebehind:
public ObservableCollection<GroupItem> GroupItems { get; set; } = new ObservableCollection<GroupItem>();
public MainPage()
{
InitializeComponent();
BindingContext = this;
GroupItem item1 = new GroupItem();
item1.Title = "Entry 1";
item1.Entries.Add(new Entry { Time = "10:13", Name = "Johnny", Amount = "10,24$" });
item1.Entries.Add(new Entry { Time = "12:11", Name = "Some long name that will be truncated", Amount = "20,14$" });
item1.Entries.Add(new Entry { Time = "10:13", Name = "Mike", Amount = "14,27$" });
GroupItems.Add(item1);
GroupItem item2 = new GroupItem();
item2.Title = "Entry 2";
item2.Entries.Add(new Entry { Time = "11:13", Name = "Finn", Amount = "10,24$" });
item2.Entries.Add(new Entry { Time = "14:11", Name = "Some long name that will be truncated", Amount = "20,14$" });
GroupItems.Add(item2);
GroupItem item3 = new GroupItem();
item3.Title = "Entry 3";
item3.Entries.Add(new Entry { Time = "11:13", Name = "Finn", Amount = "10,24$" });
item3.Entries.Add(new Entry { Time = "14:11", Name = "Some long name that will be truncated", Amount = "20,14$" });
item3.Entries.Add(new Entry { Time = "14:11", Name = "Martin", Amount = "50,15$" });
item3.Entries.Add(new Entry { Time = "14:11", Name = "Elon musk", Amount = "30,14$" });
GroupItems.Add(item3);
}
public class GroupItem
{
public string Title { get; set; }
public List<Entry> Entries { get; set; } = new List<Entry>();
}
public class Entry
{
public string Time { get; set; }
public string Name { get; set; }
public string Amount { get; set; }
}
This gives you the possibility of a dynamic amount of rows, and every group is selectable.
Result:

Xamarin MVVM Reference Content View and Pass Parameters Too

Working in xamarin forms. How do I reference a content view from a content page but also include passing information like below?
await Navigation.PushAsync(new SecondContentPage(new NextViewModel(FirstViewModel.id)));
I've tried xaml binding context but don't know where to go from there and it keeps giving me errors about a parameterless constructor.
xmlns:viewmodel="clr-namespace:Project.ViewModels"
<StackLayout>
<local:SecondContentView>
<local:SecondContentView.BindingContext>
<viewmodel:NextViewModel></viewmodel:NextViewModel>
</local:SecondContentView.BindingContext>
</local:SecondContentView>
</StackLayout>
I need the id passed along basically so that the list can run on the content view. thanks all
Updated - I created some new example code. I created one page to nest a second page with a Listview. Works great until I try to pass a parameter with x:Arguments or in a ViewModel constructor from first page to second page.
First page
**<StackLayout>
<StackLayout>
<Label Text="First Page Content"></Label>
</StackLayout>
<StackLayout>
<local:SecondContentView>
<local:SecondContentView.BindingContext>
<viewmodel:SecondViewModel>
<x:Arguments>102</x:Arguments>
</viewmodel:SecondViewModel>
</local:SecondContentView.BindingContext>
</local:SecondContentView>
</StackLayout>
</StackLayout>**
second page
<ContentView.Content>
<StackLayout>
<Label Text="Second Page"></Label>
<ListView x:Name="FirstListView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding pType}"></Label>
<Label Text="{Binding fDepartment}"></Label>
<Label Text="{Binding Description}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentView.Content>
second page's code behind
SecondViewModel ViewModel;
public SecondContentView(SecondViewModel viewmodel)
{
InitializeComponent();
BindingContext = ViewModel = viewmodel;
FirstListView.ItemsSource = ViewModel.TypeList;
}
second page's view model
**public List<TypeModel> TypeList;
public SecondViewModel(int parameter)
{
var p = parameter;
TypeList = new List<TypeModel>()
{
new TypeModel { pType = 1, Title = "First Type", Description = "First Description", Version = "9.9.9", fDepartment = 101 , Comments = "None"},
new TypeModel { pType = 2, Title = "Second Type", Description = "Second Description", Version = "9.9.9", fDepartment = 101 , Comments = "None"},
new TypeModel { pType = 3, Title = "Third Type", Description = "Third Description", Version = "9.9.9", fDepartment = 102 , Comments = "None"},
new TypeModel { pType = 4, Title = "Fourth Type", Description = "Fourth Description", Version = "9.9.9", fDepartment = 102 , Comments = "None"}
};
}**
I was able to find a solution with another mocked example. The key was x:Argument and an override method.
Firstly, if you want to pass the simple type values we need to explicitly point out its type. Try this format:
<StackLayout>
<local:SecondContentView>
<local:SecondContentView.BindingContext>
<local:SecondViewModel>
<x:Arguments>
<x:Double>102</x:Double>
</x:Arguments>
</local:SecondViewModel>
</local:SecondContentView.BindingContext>
</local:SecondContentView>
</StackLayout>
Change its constructor like:
public SecondViewModel(double parameter)
{
var p = parameter;
TypeList = new List<TypeModel>()
{
new TypeModel { pType = 1, Title = "First Type", Description = "First Description", Version = "9.9.9", fDepartment = 101 , Comments = "None"},
new TypeModel { pType = 2, Title = "Second Type", Description = "Second Description", Version = "9.9.9", fDepartment = 101 , Comments = "None"},
new TypeModel { pType = 3, Title = "Third Type", Description = "Third Description", Version = "9.9.9", fDepartment = 102 , Comments = "None"},
new TypeModel { pType = 4, Title = "Fourth Type", Description = "Fourth Description", Version = "9.9.9", fDepartment = 102 , Comments = "None"}
};
}
Secondly, you are not passing parameters to the second view's constructor. Instead, you consumed the defualt null parameter constructor and set its binding context directly. So the public SecondContentView(SecondViewModel viewmodel) won't be triggered. We could consume the binding context directly in your second view like:
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
ViewModel = BindingContext as SecondViewModel;
FirstListView.ItemsSource = ViewModel.TypeList;
}
You would just set the BindingContext for SecondContentPage to NextViewModel.
In SecondContentPage.xaml.cs constructor:
public SecondContentPage(NextViewModel vm)
{
InitializeComponent();
localVm = vm;
BindingContext = localVm;
}
private readonly NextViewModel localVm;
Then you would access the property where FirstViewModel.Id is stored in NextViewModel in xaml using a binding. For this example we'll say the Id was stored in NextViewModel.Id. Example using Label:
<Label Text="{Binding Id}"/>

Getting content of checkboxes in xaml.cs in Silverlight

I am new to silverlight. I am trying to generate a list of checkboxes(with content). The idea is that the user will select some of these checkboxes and will press a button. Then we try to read the content of selected checkboxes for further processing. I don't know how many number of checkboxes will be there and therefore I can't use bindings.
This is the code snippet in the .xaml file.
<StackPanel Grid.Row="21" Grid.Column="1" Margin="5" VerticalAlignment="Center">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ItemsControl Name="infoPairItems" ItemsSource="{Binding InfoPair}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Grid.Column="0" Name="infoPairSelectBox" IsEnabled="True" IsThreeState="False"
Margin="0,5" FontSize="12" IsChecked="bool"
Content="{Binding Converter={StaticResource infoPairToStringValueConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</StackPanel>
I am trying to access these checkboxes in the .xaml.cs file like this.
foreach(var infoPairItem in infoPairItems.Items)
{
ContentPresenter container = infoPairItems.ItemContainerGenerator.ContainerFromItem(infoPairItem) as ContentPresenter;
if(container == null)
{
DebugLog.Log("container is null ");
}
DataTemplate dataTemplate = container.ContentTemplate;
CheckBox checkBox = (CheckBox)dataTemplate.LoadContent();
if (checkBox == null)
{
DebugLog.Log("checkBox is null !!!");
return;
}
if (checkBox.IsChecked.HasValue)
{
if (checkBox.IsChecked.Value)
{
DebugLog.Log("checkbox value true");
}
else
{
DebugLog.Log("checkbox value false");
}
}
}
The log 'checkbox value false' is always getting printed for all the checkboxes even when some of them are selected. I tried to use the debugger. It looks like that variable container is getting loaded with the correct value. Either the method LoadContent() is not working or I am using the wrong method.
I apologize beforehand if it is a repeat question. I tried to look into the previous questions on stackoverflow but could not find any answer. Please guide me in correct direction.
I will explain what happens and how to solve:
1.- You are getting the datatemplate not instances of the datatemplate, in case you want to manage the instances you can do by using the Loaded Event to add items to the List to create and update for instance a List.
2.- What makes all of these events a really complex code to manage is easier if you create the following:
2.1 A class for instance that has a bool and a string for the content with INotifyPropertyChanged:
public class InfoSelection : Model
{
Property bool for Selected
Property string for Info, or whatever and the converter
}
2.2 A list with the items you need of the type of that class in the DataContext
public List<InfoSelection> {get;set;}
(If you initialize just once in the constructor for instance, you do not need to implement INotiyPropertyChanged, just clear or removeitems, never reassign)
2.3 In the Xaml binding change to the following:
<CheckBox Grid.Column="0"
Name="infoPairSelectBox"
IsEnabled="True"
IsThreeState="False"
Margin="0,5"
FontSize="12"
IsChecked="{Binding Selected, Mode=TwoWay}"
Content="{Binding Info}"/>
I don't know how many number of checkboxes will be there and therefore I can't use bindings.
Incorrect.
To Visually display two levels of data generically, the use of a ItemsControl with individual DataTemplate`s for the parent items and their child items can be done.
Then to allow for the editing (your deletion operation) one needs to identify who the parent node is from the child nodes, along with getting the state of the checkbox.
That identification requires us to project the initial data into a wrapper class to facilitate binding/identification.
Let me explain.
Say our data displays a top level last name and all first names associated with the last name.
The above simulates a top level checkbox (to delete all) and children checkbox (to delete an individual item) for the following data class retrieved from the database:
public class VectorStrings
{
public int Id { get; set; }
public string LastName { get; set; }
public List<string> FirstNames { get; set; }
}
With simulated data loaded as such:
LastNames = new List<VectorStrings>()
{
new VectorStrings() { Id=9, LastName="Smith", FirstNames = new List<string>() { "Bob", "Victoria" } },
new VectorStrings() { Id=12, LastName="Jones", FirstNames = new List<string>() { "Peter", "Paul", "Mary" } },
};
Now for display I can generically display those items to the above data, but because we need to operate on the child data, we need to project that information into a holding wrapper class.
public class VectorCheckbox
{
public int Id { get; set; }
public int ParentId { get; set; }
public string DisplayName { get; set; }
public List<VectorCheckbox> Children { get; set; }
public object Tag { get; set; } // Same concept as a visual control property 'Tag'
}
so our code to project the original data looks like this:
CheckBoxData =
LastNames.Select(ln => new VectorCheckbox()
{
DisplayName = ln.LastName,
Id = ln.Id,
Tag = ln,
Children = ln.FirstNames.Select((fn, index) => new VectorCheckbox()
{
Id = index,
ParentId = ln.Id,
DisplayName = fn,
Tag = ln.Id // Hold the parent Id for identification
}).ToList()
})
.ToList();
Sweet! Now we just need nested ItemControl classes to display our data:
<ItemsControl ItemsSource="{Binding CheckBoxData}">
<ItemsControl.Resources>
<system:String x:Key="Format">Delete All for ID: '{0}' </system:String>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" Margin="10" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="6,0,0,0">
<CheckBox Tag="{Binding Id}" Margin="0,0,0,10" Click="DeleteAll_Click">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id, StringFormat={StaticResource Format}}"/>
<TextBlock Text="{Binding DisplayName}" Margin="4,0,6,0"/>
<ItemsControl ItemsSource="{Binding Children}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Tag="{Binding Tag}"
Content="{Binding DisplayName}"
Click="DeleteIndividual_Click"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</CheckBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
Now in code behind we subscribe to the click events. I use a message box to show that I have identified the right items. For example if one clicks on a delete all check box, it identifies the children and the state of the checkbox, and if I click on a child it identifies its parent and itself.
Parent Click
private void DeleteAll_Click(object sender, RoutedEventArgs e)
{
var cb = sender as CheckBox;
if (cb != null)
{
var id = (int)cb.Tag;
var nameInstance = ViewModel.LastNames.FirstOrDefault(nm => nm.Id == id);
if (nameInstance != null)
MessageBox.Show(string.Format("Delete all for {0} of names {1} (Status {2})",
nameInstance.LastName,
string.Join(",", nameInstance.FirstNames),
((cb.IsChecked ?? false) ? "Checked" : "UnChecked")
));
}
}
Child Click
private void DeleteIndividual_Click(object sender, RoutedEventArgs e)
{
var cb = sender as CheckBox;
if (cb != null)
{
var parentId = (int)cb.Tag; // Parent Id
var nameInstance = ViewModel.LastNames.FirstOrDefault(nm => nm.Id == parentId);
if (nameInstance != null)
MessageBox.Show(string.Format("Delete individual for {0} of name {1} (Status {2})",
nameInstance.LastName,
cb.Content,
((cb.IsChecked ?? false) ? "Checked" : "UnChecked")
));
}
}
So from that I have identified the checkbox state along with the target original items. This code simulates ultimately what you want to do. I leave the actual plumbing of the observable collection remove items up to you. But this gets the idea across.
I recommend that you experiment in WPF then take it to Silverlight, for the concepts are the same, but its easier/faster to test out in WPF.

How to list AlbumArt from MediaLibrary on WP?

I've been looking for a long time how to list album cover from Windows Phone Media Library, but I didn't found any answer.
I'm developping a music player for wp8, and actually I can successfully list album info as album name, artist name, duration, etc, but I can't get the AlbumArt.
Here is the code I'm actually using :
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="AlbumInfoTemplate">
<StackPanel VerticalAlignment="Top" Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Image Source=" " Margin="5" Height="80" Width="80" Stretch="UniformToFill"/>
<StackPanel Grid.Column="1">
<TextBlock FontWeight="Normal" Text="{Binding Name}" Margin="10,0,0,0" FontSize="25" Foreground="Black"/>
<TextBlock FontWeight="Normal" Text="{Binding Artist}" Margin="10,0,0,0" FontSize="20" Foreground="Black" Opacity="0.75"/>
</StackPanel>
</Grid>
</StackPanel>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<phone:LongListSelector
x:Name="llsAlbums"
SelectionChanged="llsAlbums_SelectionChanged"
Margin="0,-35,0,0"
JumpListStyle="{StaticResource JumpListStyle}"
Background="Transparent"
GroupHeaderTemplate="{StaticResource GroupHeaderTemplate}"
ItemTemplate="{StaticResource AlbumInfoTemplate}"
LayoutMode="List"
IsGroupingEnabled="true"
HideEmptyGroups ="true"/>
Hope you could help me guys !
Before anything you need to do a small modification to the LongListSelector definition in XAML. Add this ItemsSource="{Binding}" to it. Then is should look like this.
<phone:LongListSelector
x:Name="llsAlbums"
SelectionChanged="llsAlbums_SelectionChanged"
Margin="0,-35,0,0"
JumpListStyle="{StaticResource JumpListStyle}"
Background="Transparent"
GroupHeaderTemplate="{StaticResource GroupHeaderTemplate}"
ItemTemplate="{StaticResource AlbumInfoTemplate}"
LayoutMode="List"
IsGroupingEnabled="true"
HideEmptyGroups ="true"
ItemsSource="{Binding}"/>
Since you are using JumpLists and GroupHeaders in the LongListSelector, you need to to more work than usual. Start off with creating a class to hold the Album information. Lets call it MusicAlbum Its like this.
public class MusicAlbum
{
public string Name { get; set; }
public string Artist { get; set; }
public BitmapImage Art { get; set; }
}
Then create this class and methods included for the GroupHeaders and JumpLists to work.
public class AlphaKeyGroup<T> : List<T>
{
public delegate string GetKeyDelegate(T item);
public string Key { get; private set; }
public AlphaKeyGroup(string key)
{
Key = key;
}
private static List<AlphaKeyGroup<T>> CreateGroups(SortedLocaleGrouping slg)
{
List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>();
foreach (string key in slg.GroupDisplayNames)
{
list.Add(new AlphaKeyGroup<T>(key));
}
return list;
}
public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort)
{
SortedLocaleGrouping slg = new SortedLocaleGrouping(ci);
List<AlphaKeyGroup<T>> list = CreateGroups(slg);
foreach (T item in items)
{
int index = 0;
index = slg.GetGroupIndex(getKey(item));
if (index >= 0 && index < list.Count)
{
list[index].Add(item);
}
}
if (sort)
{
foreach (AlphaKeyGroup<T> group in list)
{
group.Sort((c0, c1) => { return ci.CompareInfo.Compare(getKey(c0), getKey(c1)); });
}
}
return list;
}
}
Here i have written a small method to get the Album Art for the album, this makes it easy.
private BitmapImage GetAlbumArt(Album album)
{
BitmapImage img = new BitmapImage();
img.DecodePixelHeight = 80;
img.DecodePixelWidth = 80;
img.SetSource(album.GetAlbumArt());
return img;
}
Then this actual methods gets the list of albums from the MediaLibrary and makes a list of MusicAlbums we can use in the LLS
public List<MusicAlbum> GetAlbums()
{
if (lib == null)
lib = new MediaLibrary();
List<MusicAlbum> albumList = new List<MusicAlbum>();
var albums = lib.Albums;
foreach (var album in albums)
{
albumList.Add(new MusicAlbum()
{
Name = album.Name,
Artist = album.Artist.Name,
Art = album.HasArt ? GetAlbumArt(album) : null
});
}
return albumList;
}
After doing this, you need to make the list and set the ItemSource of the LongListSelector. In the Constructor of the page or in OnNavigatedTo method add this code.
List<AlphaKeyGroup<MusicAlbum>> albumList = AlphaKeyGroup<MusicAlbum>.CreateGroups(this.GetAlbums() as List<MusicAlbum>, Thread.CurrentThread.CurrentUICulture, (MusicAlbum s) => { return s.Name; }, true);
llsAlbums.ItemsSource = albumList;
Then you are done, run the app and you will see the albums listed..

wp8 : how to insert map into PanoramaItem HeaderTemplate

I'm trying to insert map control into PanoramaItem Header in my App :
<phone:PanoramaItem Orientation="Horizontal" Width="480">
<phone:PanoramaItem.HeaderTemplate>
<DataTemplate>
<StackPanel Height="155" Width="478" Margin="-23,0,0,0">
<!-- Map -->
<maps:Map x:Name="StationsMapOverview"
Visibility="{Binding IsDataLoaded, Converter={StaticResource BooleanToVisibilityConverter}}"
Height="115"
Margin="0,-34,0,0"
ZoomLevel="10"
Center="{Binding UserGeoCoordinate, Mode=TwoWay}"
CartographicMode="Road"
ColorMode="Light"
PedestrianFeaturesEnabled="True"
LandmarksEnabled="True"/>
</StackPanel>
</DataTemplate>
</phone:PanoramaItem.HeaderTemplate>
<!-- Stations list -->
<phone:LongListSelector x:Name="ListNearbyItems"
ItemsSource="{Binding StationItems}" Margin="0,-38,0,0" Height="480">
...
The result is good and my map appears well.
But in the behind code, I have the following error:
name 'StationsMapOverview' does not exist in the current context
(Datacontext is set by ViewModelLocator class and work fine for others pages).
And 'center' option binding is not working.
So my question is, is that someone has tried to integrate a map into PanoramaItem Header ?
To pass DataContext inside header template add:
<phone:PanoramaItem Header={Binding} x:Name="panorama"
You can't access an object in template by name. Use code below to find element by name:
private T FindElementInVisualTree<T>(DependencyObject parentElement, string name) where T : DependencyObject
{
var count = VisualTreeHelper.GetChildrenCount(parentElement);
if (count == 0)
return null;
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parentElement, i);
if (child != null && child is FrameworkElement && (child as FrameworkElement).Name.Equals(name))
{
return (T)child;
}
else
{
var result = FindElementInVisualTree<T>(child, name);
if (result != null)
return result;
}
}
return null;
}
And then call:
Map map = FindElementInVisualTree<Map>(panorama, "StationsMapOverview");