I am creating Windows UWP app that displays weather forecasts from a nestedlist sortedDays
. It contains days on the Outer list and hourly forecasts in the inner list. (using pivot)I am trying to display in each pivotItem, a separate stackPanel for every hourly forecast so that each pivotItem
will have numerous stackPanels of hourly forecast.
Unfortunately my data is running off the bottom of the screen and I cannot seem to get a scroll bar working. I have also been struggling with adding any form of margin or boarder around the hourStack
stackPanels. As the data is is coming from a nested list generated from an API I feel it must be added through c# code and not xaml(open to opinions). I have looked up the documentation but cant find anything that works through c#
//dynamically add a pivot item
PivotItem pvt;
ScrollViewer scroll;
//loop through SortedDays to seperate Day and hour forecasts
int xCount = 0, yCount = 0;
foreach (var sd in myForecast.SortedDays)
{// Define a ScrollViewer
scroll = new ScrollViewer
{
VerticalScrollBarVisibility = ScrollBarVisibility.Visible
};
pvt = new PivotItem
{
Header = myForecast.SortedDays[xCount][0].dayOfWeek
};
var dayStack = new StackPanel();
foreach (var sh in sd)
{
var hourStack = new StackPanel
{
HorizontalAlignment = HorizontalAlignment.Center
};
var timeBlock = new TextBlock
{
Text = myForecast.SortedDays[xCount][yCount].dtime,
FontSize = 30
};
hourStack.Children.Add(timeBlock);
var tempBlock = new TextBlock
{
Text = "Tempeture (c)\t:" + System.Convert.ToString(Math.Truncate((myForecast.SortedDays[xCount][yCount].temp - 273.15) * 100) / 100)
};
hourStack.Children.Add(tempBlock);
var descBlock = new TextBlock
{
Text = myForecast.SortedDays[xCount][yCount].desc
};
hourStack.Children.Add(descBlock);
var windBlock = new TextBlock
{
Text = "Windspeed\t:" + System.Convert.ToString(myForecast.SortedDays[xCount][yCount].windSpeed)
};
hourStack.Children.Add(windBlock);
var humBlock = new TextBlock
{
Text = "Humidity\t:" + System.Convert.ToString(myForecast.SortedDays[xCount][yCount].humidity)
};
hourStack.Children.Add(humBlock);
// append hourStack to dayStack
yCount++;
dayStack.Children.Add(hourStack);
}
scroll.Content = dayStack;
// set dayStack as pivots content
pvt.Content = scroll;
// add pivotItem to pivot
pvtWeather.Items.Add(pvt);
pvt = null;
xCount++;
yCount = 0;
}
WeatherPage.xaml
<Page
x:Class="WeatherForecast.WeatherPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WeatherForecast"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Pivot x:Name="pvtWeather" Margin="100,100,100,100" Height="1200" HorizontalAlignment="Center" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.BringIntoViewOnFocusChange="True">
</Pivot>
</Grid>
Before trying to set above properties code behind, actually all the elements and styles used in above code snippet could be defined in XAML. For your scenario, PivotItem
is strongly recommended to bind with data sources. Details for binding please reference this tutorial. And a nested list could be bound to Pivot
control.
Just for example, you may define the entities as follows:
public class Daylist
{
public string Day { get; set; }
public ObservableCollection<TimeTemperature> Temperatures { get; set; }
}
public class TimeTemperature
{
public string currenttime { get; set; }
public string winSpeed { get; set; }
public string humidity { get; set; }
public string temperature { get; set; }
}
So that the nested list could be created as follows:
public ObservableCollection<Daylist> daylists { get; set; }
public MainPage()
{
this.InitializeComponent();
daylists = new ObservableCollection<Daylist>
{
new Daylist {Day="Wednesday" ,Temperatures= new ObservableCollection<TimeTemperature>
{
new TimeTemperature {currenttime="2018-3-14 00:00:00",temperature="7.72",winSpeed="11.67" ,humidity=".95"},
new TimeTemperature {currenttime="2018-3-14 01:00:00",temperature="7.72",winSpeed="11.67" ,humidity=".95" },
new TimeTemperature {currenttime="2018-3-14 02:20:00",temperature="7.72",winSpeed="11.67" ,humidity=".95"}
...
}},
new Daylist {Day="Friday" ,Temperatures= new ObservableCollection<TimeTemperature>
{
new TimeTemperature {currenttime="2018-3-14 00:00:00",temperature="7.72",winSpeed="11.67" ,humidity=".95" }
}}
};
}
And now we can define the elements in XAML and bind data source to Pivot
and PivotItem
, the layout can be simply updated. For your requirements, using a ListView
for Pivot.ItemTemplate
to show the data , it will auto scroll when records are overflow. You can also add Margin
and other properties as you want.
<Pivot x:Name="Pivot1" ItemsSource="{x:Bind daylists}">
<Pivot.HeaderTemplate>
<DataTemplate x:DataType="local:Daylist">
<TextBlock Text="{x:Bind Day}" />
</DataTemplate>
</Pivot.HeaderTemplate>
<Pivot.ItemTemplate>
<DataTemplate x:DataType="local:Daylist">
<ScrollViewer>
<ListView ItemsSource="{x:Bind Temperatures}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:TimeTemperature">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.ColumnSpan="2"
Text="{x:Bind currenttime}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Text="winSpeed:" />
<TextBlock
Grid.Row="1"
Grid.Column="1"
Text="{x:Bind winSpeed}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Text="humidity:" />
<TextBlock
Grid.Row="2"
Grid.Column="1"
Text="{x:Bind humidity}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Text="temperature:" />
<TextBlock
Grid.Row="3"
Grid.Column="1"
Text="{x:Bind temperature}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
</DataTemplate>
</Pivot.ItemTemplate>
</Pivot>
More details please reference the official sample.