Filling ComboBox and SelectedValue Elements in a ComboBox in the GridView DataTemplate

I am developing a universal Windows 10 application, and I am having problems getting items to populate in the ComboBox (both ComboBox and SelectedValue elements) that are inside the GridView DataTemplate. I can't seem to find a way to do this.

Here are the details:

I have an object ( UserData ) that can contain multiple instances of another object ( List<VisitedCity> ). On the XAML page, multiple VisitedCity instances VisitedCity displayed on the vertical GridView.

Each VisitedCity instance may contain CityName and VisitedDate . On the XAML page, the name CityName should be displayed in the ComboBox and the visited DatePicker date date inside each GridViewItem.

What does not work:

In the ComboBox showing the selected city name for each VisitCity, the list of elements loaded from the List<string> variable must be specified (so that the user can change it), and the ComboBox SelectedValue must be loaded from the curretUserData VisitedCities property (CityName property).

I am trying to do this with x:Bind on XAML to minimize code.

I included all of my code from the sample application I made to fix this problem, and also indicated the XAML line of code that I'm having problems with.

Note that this is a very simplified part of a larger application with VisistedCities as an example, so the problem can be demonstrated better. Thank you for your help and help!

Here is my class file:

 namespace mySampleApp { class UserData { public string FullName { get; set; } public List<VisitedCity> VisitedCities { get; set; } } class VisitedCity { public string CityName { get; set; } public DateTime VisitedDate { get; set; } } class CityNameManager { public static List<string> GetListOfCitiesFromServer() { List<string> listOfCities = new List<string>(); //code will be here to get the latest list from the server. for now we will manually return a list listOfCities.Add("City1"); listOfCities.Add("City2"); listOfCities.Add("City3"); listOfCities.Add("City4"); listOfCities.Add("City5"); return listOfCities; } } } 

Here is my XAML:

 <Page x:Class="mySampleApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:mySampleApp" 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}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBox x:Name="txtFirstName" Grid.Row="0" Header="Enter Your Name" Text="{x:Bind curretUserData.FullName}"/> <TextBlock x:Name="label1" Grid.Row="1" TextWrapping="WrapWholeWords" Text="Please select all cities you have visited during the last 5 years. For each city please enter the data visited. If you visited a city multiple times, please have multiple entries for each time indicating the date visited each time." /> <TextBlock x:Name="label2" Grid.Row="2" TextWrapping="WrapWholeWords" Text="Press the + button to add rows as needed. " /> <Button x:Name="myButton" Grid.Row="3" Content="+" Click="myButton_Click" /> <GridView x:Name="myGridView" Grid.Row="4" HorizontalContentAlignment="Stretch" SelectionMode="None" ItemsSource="{x:Bind curretUserData.VisitedCities}"> <GridView.ItemsPanel> <ItemsPanelTemplate> <ItemsStackPanel Orientation="Vertical" /> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="HorizontalAlignment" Value="Stretch"/> </Style> </GridView.ItemContainerStyle> <GridView.ItemTemplate> <DataTemplate x:DataType="local:VisitedCity"> <Grid HorizontalAlignment="Stretch"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <!-- This is the line of code which has issues--> <ComboBox Grid.Column="0" x:Name="myTemplateComboBox" ItemsSource="{local:CityList ??? }" SelectedValue="{x:Bind CityName ??? }" HorizontalAlignment="Stretch" /> <DatePicker Grid.Column="1" x:Name="myTemplateDatePicker" Date="{x:Bind VisitedDate }" /> </Grid> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid> </Page> 

Here is my code:

 namespace mySampleApp { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { //variables to use in XAML x:Bind private UserData curretUserData = new UserData(); private List<string> CityList = new List<string>(); public MainPage() { //get latest list of cities from the server CityList = CityNameManager.GetListOfCitiesFromServer(); //add sample data to show on the page for demo curretUserData.FullName = "Sample User"; List<VisitedCity> sampleUserVisitedCities = new List<VisitedCity>(); sampleUserVisitedCities.Add(new VisitedCity {CityName = "City1", VisitedDate=DateTime.Parse("2/2/2016") }); sampleUserVisitedCities.Add(new VisitedCity {CityName = "City2", VisitedDate = DateTime.Parse("2/2/2015") }); curretUserData.VisitedCities = sampleUserVisitedCities; this.InitializeComponent(); } private void myButton_Click(object sender, RoutedEventArgs e) { //add a new row GridViewItem gridViewItem = new GridViewItem(); gridViewItem.ContentTemplate = myGridView.ItemTemplate; myGridView.Items.Add(gridViewItem); } } } 
0
source share
1 answer

You need to change your anchor expression to capture from the parent page. x: Bind will only use the local DataContext, which in this case is a template.

 <ComboBox Grid.Column="0" x:Name="myTemplateComboBox" ItemsSource="{Binding ElementName=MyPage, Path=CityList }" SelectedValue="{x:Bind CityName, Mode=TwoWay}" HorizontalAlignment="Stretch" /> 

In this case, I make CityList public, and then named the page so that we can capture it with ElementName .

You also need to enable TwoWay binding TwoWay that you can return values ​​to your data model after the user makes changes.

If you use the Observable collection instead of List, you can add a GridView to your rows by changing the data model. Otherwise, I made an exception.

I also changed the original username for PlaceholderText so that the user does not delete the sample name in order to type them.

Full code

 <Page x:Class="SOCityGridView.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:SOCityGridView" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="MyPage" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBox x:Name="txtFirstName" Grid.Row="0" Header="Enter Your Name" Text="{x:Bind currentUserData.FullName}" PlaceholderText="Sample User"/> <TextBlock x:Name="label1" Grid.Row="1" TextWrapping="WrapWholeWords" Text="Please select all cities you have visited during the last 5 years. For each city please enter the data visited. If you visited a city multiple times, please have multiple entries for each time indicating the date visited each time." /> <TextBlock x:Name="label2" Grid.Row="2" TextWrapping="WrapWholeWords" Text="Press the + button to add rows as needed. " /> <Button x:Name="myButton" Grid.Row="3" Content="+" Click="myButton_Click" /> <GridView x:Name="myGridView" Grid.Row="4" HorizontalContentAlignment="Stretch" SelectionMode="None" ItemsSource="{x:Bind currentUserData.VisitedCities}"> <GridView.ItemsPanel> <ItemsPanelTemplate> <ItemsStackPanel Orientation="Vertical" /> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="HorizontalAlignment" Value="Stretch"/> </Style> </GridView.ItemContainerStyle> <GridView.ItemTemplate> <DataTemplate x:DataType="local:VisitedCity"> <Grid HorizontalAlignment="Stretch"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <!-- This is the line of code which has issues--> <ComboBox Grid.Column="0" x:Name="myTemplateComboBox" ItemsSource="{Binding ElementName=MyPage, Path=CityList }" SelectedValue="{x:Bind CityName, Mode=TwoWay}" HorizontalAlignment="Stretch" /> <DatePicker Grid.Column="1" x:Name="myTemplateDatePicker" Date="{x:Bind VisitedDate, Mode=TwoWay}" /> </Grid> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid> </Page> 

And the code behind:

 using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 namespace SOCityGridView { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { //variables to use in XAML x:Bind private UserData currentUserData = new UserData(); public List<string> CityList { get; set; } = new List<string>(); public MainPage() { //get latest list of cities from the server CityList = CityNameManager.GetListOfCitiesFromServer(); //add sample data to show on the page for demo List<VisitedCity> sampleUserVisitedCities = new List<VisitedCity>(); sampleUserVisitedCities.Add(new VisitedCity { CityName = "City1", VisitedDate = DateTime.Parse("2/2/2016") }); sampleUserVisitedCities.Add(new VisitedCity { CityName = "City2", VisitedDate = DateTime.Parse("2/2/2015") }); currentUserData.VisitedCities = new ObservableCollection<VisitedCity>(sampleUserVisitedCities); this.InitializeComponent(); } private void myButton_Click(object sender, RoutedEventArgs e) { currentUserData.VisitedCities.Add(new VisitedCity { CityName = "City1", VisitedDate = DateTime.Now }); } } public class UserData { public string FullName { get; set; } public ObservableCollection<VisitedCity> VisitedCities { get; set; } } public class VisitedCity { public string CityName { get; set; } public DateTimeOffset VisitedDate { get; set; } } public class CityNameManager { public static List<string> GetListOfCitiesFromServer() { List<string> listOfCities = new List<string>(); //code will be here to get the latest list from the server. for now we will manually return a list listOfCities.Add("City1"); listOfCities.Add("City2"); listOfCities.Add("City3"); listOfCities.Add("City4"); listOfCities.Add("City5"); return listOfCities; } } } 
+2
source

Source: https://habr.com/ru/post/1275526/


All Articles