2

I have the following XAML code that used on hub application for windows 8.1:

<HubSection Width="780" Margin="0,0,80,0">
                <HubSection.Background>
                    <ImageBrush ImageSource="Assets/MediumGray.png" Stretch="UniformToFill" />
                </HubSection.Background>
                <DataTemplate>
                    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
                        <m:Map Credentials="YOUR_BING_MAPS_KEY">
                            <m:Map.Children>
                                <!-- Data Layer-->
                                <m:MapLayer Name="DataLayer"/>

                                <!--Common Infobox-->
                                <m:MapLayer>
                                    <Grid x:Name="Infobox" Visibility="Collapsed" Margin="0,-115,-15,0">
                                        <Border Width="300" Height="110" Background="Black" Opacity="0.8" BorderBrush="White" BorderThickness="2" CornerRadius="5"/>

                                    </Grid>
                                </m:MapLayer>
                            </m:Map.Children>
                        </m:Map>
                    </Grid>

                </DataTemplate>
            </HubSection>

The problem is that I can't access to MapLayer and to the Grid controls in the c# page. (The problem happens only whe the XAML is inside the DataTepmlate control). How can I get this access?

Nave Tseva
  • 868
  • 8
  • 24
  • 47
  • Add a name to your Grid and use the Control.Findname method to get your child controls – Sajeetharan Oct 08 '14 at 13:47
  • @Sajeetharan Thanks for your comment, but can you pleas post an example for how the code should look like? (When I added the name property I got an error: "The propert name is set more than once)" – Nave Tseva Oct 08 '14 at 13:57
  • Check this link http://stackoverflow.com/questions/5181063/how-to-access-a-specific-item-in-a-listbox-with-datatemplate – Sajeetharan Oct 08 '14 at 13:59
  • I answered that question yesterday: http://stackoverflow.com/questions/26236707/access-xaml-control-inside-ith-item-in-flipview/26237483#26237483 (just another sample..) – Fred Oct 08 '14 at 15:06
  • @Fred Thank you, I added the method you wrote and in this method I added this: `public HubPage() { this.InitializeComponent(); var DataLayer = FindElementByName(this, "DataLayer"); AddPushpin(new Location(47.6035, -122.3294), "Seattle", "Seattle is in the state of Washington. ", DataLayer);` The problem is that 'DataLayer' is always null, why? – Nave Tseva Oct 09 '14 at 06:34
  • @Sajeetharan I also tried your suggestion but I get null too – Nave Tseva Oct 09 '14 at 06:38
  • You have to call the method after your MapLayer is loaded which is probably not the case in your constructor. Attach a loaded event to your maplayer / map and run the code there. – Fred Oct 09 '14 at 12:35
  • @Fred How can I do it? What should I change in my code? – Nave Tseva Oct 09 '14 at 12:45
  • 1
    `` And use your code inside the handler. And please post your code here so that others can review it. – Fred Oct 09 '14 at 12:47
  • You're welcome. I will post the answer in a minute. – Fred Oct 09 '14 at 13:20

1 Answers1

2

You should use a VisualTreeHelper method. This is just some code I am using. I think you can easily adjust it to your needs.

First put the FindElementByName method somewhere into your code behind file:

public T FindElementByName<T>(DependencyObject element, string sChildName) where T : FrameworkElement
    {
        T childElement = null;
        var nChildCount = VisualTreeHelper.GetChildrenCount(element);
        for (int i = 0; i < nChildCount; i++)
        {
            FrameworkElement child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;

            if (child == null)
                continue;

            if (child is T && child.Name.Equals(sChildName))
            {
                childElement = (T)child;
                break;
            }

            childElement = FindElementByName<T>(child, sChildName);

            if (childElement != null)
                break;
        }
        return childElement;
    }

Now you can start using the method. Add an event handler to your MapLayer or to your Map like this:

<m:MapLayer Name="DataLayer" Loaded="DataLayerLoaded" />

Inside your handler you can now access the element with code like this (you might have to adjust this as I am not too familiar with the Hubsection control):

this.UpdateLayout();
// Give your hub a name using x:Name=
var item = [..] // Retrieve your hubsection here!
var container = this.MyHubSection.ContainerFromItem(item);
// NPE safety, deny first
if (container == null)
    return;
var datalayer = FindElementByName<MapLayer>(container, "DataLayer");
// And again deny if we got null
if (datalayer == null)
    return;
/*
  Start doing your stuff here.
*/
Fred
  • 3,324
  • 1
  • 19
  • 29