我正在开发一个Windows 10 Universal App,但我无法在GridView DataTemplate中的ComboBox(ComboBox项和SelectedValue)中填充项目。我似乎无法找到办法做到这一点。
以下是详细信息:
我有一个对象(UserData
),它可以包含另一个对象的多个实例(List<VisitedCity>
)。在XAML页面上,VisitedCity
的多个实例显示在垂直GridView上。
VisitedCity
的每个实例都可以包含CityName
和VisitedDate
。在XAML页面上,CityName将显示在ComboBox上,访问日期显示在每个GridViewItem内DatePicker上的Date上。
什么行不通:
显示每个VisitedCity所选城市名称的ComboBox需要从List<string>
变量加载它的项目列表(以便用户可以更改它),并且ComboBox SelectedValue需要从curretUserData对象的VisitedCities
属性(CityName属性)加载。
我尝试在XAML上使用x:Bind
执行此操作,以最大限度地减少后面的代码。
我已经将我所做的示例应用程序中的所有代码都包含在内,但我也在XAML上指出了我遇到问题的代码行。
请注意,这是以VisistedCities为例的较大应用程序的高度简化部分,以便更好地证明问题。感谢您的所有帮助和意见!
这是我的班级文件:
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;
}
}
}
这是我的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>
这是我背后的代码:
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 :(得分:2)
您需要修改绑定表达式以从父页面抓取。 x:Bind只使用本地DataContext,在本例中是模板化项目。
<ComboBox Grid.Column="0" x:Name="myTemplateComboBox" ItemsSource="{Binding ElementName=MyPage, Path=CityList }" SelectedValue="{x:Bind CityName, Mode=TwoWay}" HorizontalAlignment="Stretch" />
在这种情况下,我将CityList设为公共属性,然后命名为Page,以便我们可以使用ElementName
获取它。
您还需要启用TwoWay
绑定,以便在用户进行更改后将值设置回数据模型。
如果使用Observable集合而不是List,则可以通过修改数据模型添加到GridView行。否则我会遇到异常。
我还换掉了PlaceholderText的初始用户名,这样用户就不必删除样本名称来输入他们的名字。
完整代码
<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>
代码背后:
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;
}
}
}