toghrul-nasirli
toghrul-nasirli

Reputation: 302

How to set template for listbox in WPF(Windows 10 Weather)

I am trying to create a Windows 10 weather application in WPF using C#. I need to have a Listbox to display recent 10 day weather section. I must set template for Listbox items. I tried this:

<ListBox Grid.Row="1" x:Name="DailyWeatherListBox">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel>
                <!--...-->
            </StackPanel>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

This is the recent 10 day weather section (Windows 10 Weather)

Look the Windows 10 Weather. I put this image for disuse Windows 10. I also don't know how to set Scrollbar in the Listbox corners. I would be very thankful if you could help.

Upvotes: 2

Views: 6237

Answers (3)

Gabriel Vanca
Gabriel Vanca

Reputation: 1

<ListBox ItemsSource="{Binding WeeklyWeather}"
         SelectedItem="{Binding SelectedDailyWeather, Mode=TwoWay}">

  <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Day}"/>
                <Image Source={Binding WheatherPicturePath}/>
                <TextBlock Text="{Binding Temperature}"/>
                <TextBlock Text="{Binding Description}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>

                        <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" />
                        </ItemsPanelTemplate>
                    </ListBox.ItemsPanel>

                    <ListBox.ItemContainerStyle>
                        <Style TargetType="ListBoxItem">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                        <!--  use this place to design how container normally looks like  -->
                                        <Border
                                            x:Name="Border"
                                            Margin="0"
                                            Padding="18,10,2,8"
                                            Background="Transparent"
                                            BorderThickness="1"
                                            CornerRadius="0"
                                            SnapsToDevicePixels="True">
                                            <ContentPresenter />
                                        </Border>

                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsSelected" Value="True">
                                                <Setter TargetName="Border" Property="Background" Value="{DynamicResource ListBoxItemSelectedBackgroundThemeBrush}" />
                                                <Setter Property="Foreground" Value="{DynamicResource ListBoxItemSelectedForegroundThemeBrush}" />
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </ListBox.ItemContainerStyle>

</ListBox>

Upvotes: 0

Andrew
Andrew

Reputation: 181

You can set a simple ListBox template like this:

<ListBox Grid.Row="1" x:Name="DailyWeatherListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <!--Insert XAML for One Item-->
                <Label Content="{Binding}"/>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBoxItem>Item 1</ListBoxItem>
    <ListBoxItem>Item 2</ListBoxItem>
</ListBox>

In most real world scenarios where there is more then once piece of information per item to be displayed you would define how you want your data to be displayed through a DataTemplate. For example if I wanted to display both the high temperature and the low temperature and style them separately: I would first create a DailyWeather model in c# and create a DataTemplate for it, like so:

public class DailyWeather
{
    public int High { get; set; }
    public int Low { get; set; }
    // You Would Add All Your Other Data You Want to Display Here
}

In your page resources (or another resource dictionary like in App.xaml):

<Window.Resources>
    <DataTemplate DataType="{x:Type DailyWeather}">
         <Grid>
             <StackPanel>
                 <Label FontSize="18" Content="{Binding High}"/>
                 <Label FontSize="14" Content="{Binding Low}"/>
             </StackPanel>
         </Grid>
    </DataTemplate>
</Window.Resources>

On your ListBox no ItemTemplate is required ...

<ListBox Grid.Row="1" x:Name="DailyWeatherListBox"/>

... because once you set the source to a List<DailyWeather>, (or do a binding like Siim Haas's answer suggests) your program will find the DataTemplate we defined for a DailyWeather object that we included in the resources.

Upvotes: 2

Siim Haas
Siim Haas

Reputation: 505

I would start off something like this:

<ListBox ItemsSource="{Binding WeeklyWeather}"
         SelectedItem="{Binding SelectedDailyWeather, Mode=TwoWay}">

    //Use ItemTemplate to set how item looks "inside"
    //I'll leave design details for you
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Day}"/>
                <Image Source={Binding WheatherPicturePath}/>
                <TextBlock Text="{Binding Temperature}"/>
                <TextBlock Text="{Binding Description}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>

    //ItemsPanel defines container for items. It can be StackPanel, Wrapanel, Grid, etc
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel IsItemsHost="True" Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        //You use this place to design how container normally looks like
                        <Border Background="White">
                            //DataTemplate defined above is placed in ContentPresenter
                            <ContentPresenter />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                //Here we catch "IsSelected" event and re-design our template to visually reflect "selected"
                <Trigger Property="IsSelected" Value="true">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <Border Background="Gray">
                                    <ContentPresenter />
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>

</ListBox>

Here are couple ideas how for those bindings.

public class WeatherViewModel
{
    public string Day { get; set; }
    public string WheatherPicturePath { get; set; }
    public string Temperature { get; set; }
    public string Description { get; set; }
}

public class BindedDataContext
{
    public ObservableCollection<WeatherViewModel> WeeklyWeather { get; set; }
    public WeatherViewModel SelectedDailyWeather { get; set; }
    //...
}

Your approaches for code-behind may differ, but they need to be in place for you to use those bindings.

For such scrollbar I would look into Change scrollviewer template in listbox

Upvotes: 5

Related Questions