Search code examples
c#xamluwppivotcomputer-science

UWP Grid inside Datatemplate


I have a Pivot where I set the header in my Pivot.HeaderTemplate it is basically just showing Names of Books. In my Pivot.ItemTemplate I want to show a Grid which is build in my .xaml.cs but since the Grid is in my DataTemplate I can not access the Grid x:Name anymore in the code behind in .xaml.cs. books is a Collection of Books which contains a Name and a Title

MainPage.xaml

<Pivot ItemsSource="{x:Bind books}">

<Pivot.HeaderTemplate>
    <DataTemplate x:DataType="local:Book">
        <TextBlock Text="{x:Bind Name}"/>
    </DataTemplate>
</Pivot.HeaderTemplate>

<Pivot.ItemTemplate>
    <DataTemplate>
        <Grid 
            x:Name="BooksGrid" 
            BorderBrush="Black" BorderThickness="1 1 0 0" 
            Margin="0 10 0 0>
        </Grid>
    </DataTemplate>
</Pivot.ItemTemplate>

Now I want to acces BooksGrid iny the code behind and actually create the Grid

MainPage.xaml.cs

public MainPage()
    {

        this.InitializeComponent();
    }

 private void DrawGrid()
    {

            //create columns of Grid
            for (int i = 0; i < booksize.XProperties.Count + 1; i++)
            {
                BooksGrid.ColumnDefinitions.Add(new ColumnDefinition
                {

                });

            }

            BooksGrid.ColumnDefinitions[0].Width = GridLength.Auto;
        }  

     ....

Already here at BooksGrid.ColumnDefinitions.Add(...) I get the error that BooksGrid can not be found. My DrawGrid works if I do not place the Grid definition in my DataTemplate and also outside myPivot. So the MainPage.xaml.csdoes not find it when the Grid is inside my DataTemplate

I've read that the solution might be that I have to acces the Grid instance that I want to work with, as soon as the DataTemplate gets loaded. But I do not know how to do that either.

EDIT PART to first solution:

I'm also using BooksGrid in another method MainPage.xaml.cs

private void DrawBooksFront(Front front)
    {
        int row;
        int column;
        column = booksize.XProperties.IndexOf(front.CustomProps[booksize.XLabel])+1;
        row = booksize.YProperties.IndexOf(front.CustomProps[booksize.YLabel])+1;
        Frame newFrame = new Frame();
        TaskBoardGrid.Children.Add(newFrame);
        Grid.SetColumn(newFrame, column);
        Grid.SetRow(newFrame, row);


    }

Solution

  • The reason you cannot access your BooksGrid is because it will be dynamically generated for each book in the books collection. So for every book a Grid will be generated.

    OPTION 1: You can add a Loaded event to your grid:

    <Pivot x:Name="Pivot" ItemsSource="{x:Bind books}">
        <Pivot.HeaderTemplate>
            <DataTemplate x:DataType="local:Book">
                <TextBlock Text="{x:Bind Name}"/>
            </DataTemplate>
        </Pivot.HeaderTemplate>
    
        <Pivot.ItemTemplate>
            <DataTemplate>
                <Grid 
                    BorderBrush="Black" BorderThickness="1,1,0,0" 
                    Margin="0,10,0,0" Loaded="DrawGrid">
                </Grid>
            </DataTemplate>
        </Pivot.ItemTemplate>
    

    and in your code behind:

        private void DrawGrid(object sender, RoutedEventArgs e)
        {
            Grid grid = sender as Grid;
            // Load your grid..
        }
    

    EDIT - OPTION 2: If you'd like to access your grids from code behind in a different way (like suggested in your edit) you can always do the following:

    private void DrawBooksFront(Front front)
    {
            // Loop through the pivot's items and get the content from each item's ContentTemplate.
            foreach (var item in Pivot.Items)
            {
                PivotItem pivotItem = Pivot.ContainerFromItem(item) as PivotItem;
                Grid grid = pivotItem.ContentTemplate.LoadContent() as Grid;
                // Do something with the grid.
            }
    }