在GridView DataTemplate中的ComboBox中填充ComboBox项和SelectedValue

时间:2018-02-23 19:20:14

标签: c# xaml uwp win-universal-app windows-10-universal

我正在开发一个Windows 10 Universal App,但我无法在GridView DataTemplate中的ComboBox(ComboBox项和SelectedValue)中填充项目。我似乎无法找到办法做到这一点。

以下是详细信息:

我有一个对象(UserData),它可以包含另一个对象的多个实例(List<VisitedCity>)。在XAML页面上,VisitedCity的多个实例显示在垂直GridView上。

VisitedCity的每个实例都可以包含CityNameVisitedDate。在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);
        }
    }
}

1 个答案:

答案 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;

        }
    }
}