【问题标题】:MVVM + multilevel/nested databindingMVVM + 多级/嵌套数据绑定
【发布时间】:2012-12-10 08:37:12
【问题描述】:

结构

场景是我有一个 Pivot,其中每个项目都是某一天的菜单。在该 PivotItem 中,我需要在菜单上显示菜肴,按类别分组(例如汤、甜点……)。

我已经用 MVVM 模型实现了这个。

因此我有以下模型:

public class Menu{
    public string Date;
    public List<DishList> Categories;
}
public class DishList
{
    public string Category;
    public List<Dish> Dishes;
}
public class Dish
{
    public string Name;
    public string Price;
}

编辑:这里简化了,每个字段的实际结构是这样的:

    private string _date;

    //Get_Set
    public string Date
    {
        get
        {
            return _date;
        }
        set
        {
            if (value != _date)
            {
                _date = value;
            }
        }
    }

所以结构应该是这样的:一个 PivotElement 包含一个菜单对象。在其中,我展示了类别,即一些 DishList。在该 Dishlist 中,我显示了类别和不同的菜肴,每个都有它的名称和价格。使事情更清晰的模型(SkyDrive 上的 pdf 文件); http://sdrv.ms/12IKlWd

我有以下视图模型

public class MenuViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Menu> _Menus;
}

应实现所需布局的视图(结构)如下:

<phone:Pivot 
        ItemsSource="{Binding Menus}">
        <phone:Pivot.HeaderTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Date}" />
            </DataTemplate>
        </phone:Pivot.HeaderTemplate>
        <phone:Pivot.ItemTemplate>
            <DataTemplate>
                <ItemsControl
                    ItemsSource="{Binding Categories}">   
                    <TextBlock
                        Text="{Binding Category}"/>
                    <ItemsControl
                        x:Name="Dishes"
                        ItemsSource="{Binding Dishes}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="300"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>

                                    <TextBlock 
                                        Grid.Column="1" 
                                        Text="{Binding Name}"/>
                                    <TextBlock 
                                        Grid.Column="2" 
                                        Text="{Binding Price}"/>
                                </Grid>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </ItemsControl>
            </DataTemplate>
        </phone:Pivot.ItemTemplate>
    </phone:Pivot>

如您所见,有嵌套的数据绑定来获取所需的数据。

然后我在页面上做的唯一代码是

DataContext = App.ViewModel;

问题

当我启动它时,我会在 PivotItems 标题中显示正确的数据,以及正确数量的 PivotItems。不幸的是,就是这样; PivotItem 的内容保持为空。因此,第一级数据绑定有效,但没有进一步。

我的想法

  • 第一级:每个 PivotItem 都链接到 Menu 类型的对象,标题为 Menu.Date
  • 第二级:在该 PivotItem 中,我将 ItemsControl 的 ItemsSource 设置为该 Menu.Categories
  • 第三级:ItemsSource 现在是 Menu.Categories.Dishes

我已经进行了相当多的搜索并摆弄了 Datacontext 和 ItemsSource 以及不同类型的“{Binding ...}”,但我无法让它工作。我想在 xaml 中进行绑定,而不是在代码隐藏中。

注意事项

  • 唯一的功能是显示数据。数据是固定的,并且从文件中加载一次。 这就是我选择 ItemsControl 而不是 ListBox 的原因,不需要选择任何东西。
  • 这是我上一个问题的 MVVM 方法:Databinding + Dynamic Pivot

【问题讨论】:

    标签: c# windows-phone-7 data-binding mvvm windows-phone-8


    【解决方案1】:

    首先,您正在尝试访问标题中的私有字段,因此这不起作用。这些也必须是属性,而不是字段。

    <TextBlock Text="{Binding Date}" />
    
    private string Date;
    

    接下来,您将绑定到 Category,它也是私有的,而不是属性。

    <TextBlock Text="{Binding Category}"/>
    
    private string Category;
    

    您正在绑定到需要成为属性的类别字段。

    <ItemsControl ItemsSource="{Binding Categories}">
    
    public List<DishList> Categories;
    

    即使你纠正了这些问题,你仍然无法得到你想要的,因为你的外部ItemsControl 没有ItemTemplate

    <ItemsControl ItemsSource="{Binding Categories}">   
      <TextBlock Text="{Binding Category}"/>
      ...
    </ItemsControl>
    

    补充:你的新错误是因为DataTemplate只能有一个子元素,所以你需要使用像StackPanel这样的容器。

    <ItemsControl ItemsSource="{Binding Categories}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Category}"/>
            <ItemsControl x:Name="Dishes" ItemsSource="{Binding Dishes}">
              ...
            </ItemsControl>
          </StackPanel>
         </DataTemplate>
       </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    【讨论】:

    • 请不要列出列表,ObservableCollection&lt;T&gt; 是 MVVM 中的首选集合类型。
    • 1.所有的值实际上都有属性而不是字段,但我没有在这里输入它们以保持简单。抱歉,我用真实代码中的示例编辑了帖子。
    • 2.我为外部 ItemsControl 添加了 ItemTemplate。但是,我现在在 VS 中收到错误消息“属性 VisualTree 设置不止一次”。不能将 ItemsControl 放在 ItemsControl 中吗?
    • 3.关于名单;我之前有 ObservableCollection 。但是,由于没有任何数据会改变,因此不需要 Nofitystuff 以及与之相关的开销。因此,我将其更改为列表。不过,我在 ViewModel 中使用了 ObervableCollection,因为它只在那里需要。这种推理不正确吗?
    • 是的,终于成功了!花了几个小时在数据绑定和 MVVM 概念上……谢谢!我还将列表更改为 ObservableCollections,但仍不确定这是否真的更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多