如何使用两个ObservableCollection进行数据绑定?

时间:2019-07-17 08:28:46

标签: c# xaml xamarin mvvm data-binding

我有2个模型,2个视图和1个视图模型。 基本上,我想将数据从GTSLocation对象加载到ListItem中,还要从GTSWorkingSite对象添加另外两个值,该对象具有与GTSLocation对象相同的工作地点指导。

ObservableCollection <GTSLocation>中的项目fooA:

WorkingSiteId : "A-A-A-A"
Longitude: 60
Latitude: 120

ObservableCollection <GTSLocation>中的项目fooB:

WorkingSiteId : null
Longitude: 70
Latitude: 130

ObservableCollection <GTSWorkingSite>的项barA:

Id: "A-A-A-A"
Name: "WacDonald's"
Description: "A Fastfood resturaunt."

fooA的列表项:

WorkingSiteName: "WacDonald's"
WorkingSiteDescription: "A Fastfood resturaunt."
Longitude: 60
Latitude: 120

fooB的列表项:

WorkingSiteName: "Unknown Place"
WorkingSiteDescription: "No info to provide"
Longitude: 70
Latitude: 130

我只能提出创建另一个包含我想要的所有属性的模型的解决方案。其实这是唯一的方法吗?我猜肯定有一种更优雅的方式吗?

总而言之,我拥有两个ObservableCollection的原因是因为GTSWorkingSite也分别用于另一个视图(WorkingSiteView.xaml)。

◎模型

    public class GTSLocation 
    {
        public string WorkingSiteId {get;set;} //GUID
        public double Longitude {get;set;}
        public double Latitude {get;set;}
        public DateTime Timestamp {get;set;}
    }
    public class GTSWorkingSite
    {
        public string Id {get;set;} //GUID
        public string Name {get;set;}
        public string Description {get;set;}
    }

◎ViewModel

    public class GeneralViewModel : INotifyPropertyChanged 
    {
        //Assume these two collection filled with data
        public ObservableCollection<GTSLocation> UserLocations { get; set; }
        public ObservableCollection<GTSWorkingSite> WorkingSites { get; set; }
        //Ignored the rest of the code...
    }

◎查看:UserItemsPage.xaml

   <ListView ItemsSource="{Binding UserLocations}">
   <ListView.ItemTemplate>
       <DataTemplate>
           <ViewCell>
               <Grid>
                   <Grid.RowDefinitions>
                       <RowDefinition Height="1*" />
                       <RowDefinition Height="1*" />
                       <RowDefinition Height="1*" />
                   </Grid.RowDefinitions>
                   <Grid.ColumnDefinitions>
                       <ColumnDefinition Width="100" />
                       <ColumnDefinition Width="1*" />
                       <ColumnDefinition Width="2*" />
                   </Grid.ColumnDefinitions>
                   <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" />
                   <Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding WorkingSiteName}" />
                   <Label Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding WorkingSiteDescription}" />
                   <Label Grid.Row="2" Grid.Column="1" Text="{Binding Longitude}" />
                   <Label Grid.Row="2" Grid.Column="2" Text="{Timestamp}" HorizontalTextAlignment="End" />
               </Grid>
           </ViewCell>
       </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

如果这从一开始就是一个不好的设计,如果有人可以给我建议,我愿意重构我的代码。

2 个答案:

答案 0 :(得分:0)

我认为在ListView上具有两个BindingContext,然后实际创建第三类并将这两个列表合并为一个,会更加复杂。

var newList = from locations in UserLocations
              join workingSite in WorkingSites on locations.WorkingSiteId equals workingSite.Id
              select new WhatEverClass(workingSite, locations);

WhatEverClass中,您可以拥有GTSWorkingSiteGTSLocation的后备值以及所需的任何字段/属性。

此外,在谈论重构您时,如果WorkingSiteId确实是GUID,为什么不使用GUID而不是string
+您可以将经度和纬度包装到班级中-例如GeoCoordinate,也可以使用其他逻辑创建自己的类(如果需要)。 C#是强类型?

答案 1 :(得分:0)

这很糟糕,因为您依赖两个类之间的字符串(或任何GUID)映射。如果您不想创建第三个模型,但是可以重构当前模型,并且无论如何,如果GTSLocation与GTSWorkingSite都具有1-1映射,那么我认为您可以这样做:

1)重构模型,以便GTSLocation知道它具有GTSWotkingSite的事实:

public class GTSLocation 
{
    public string WorkingSiteId {get;set;} //GUID
    public double Longitude {get;set;}
    public double Latitude {get;set;}
    public DateTime Timestamp {get;set;}
    //New property -> We will use it in the binding!
    public GTSWorkingSite WorkingSite {get;set;}
}
public class GTSWorkingSite
{
    public string Id {get;set;} //GUID
    public string Name {get;set;}
    public string Description {get;set;}
}

2)然后,在XAML中,正确填充后就很容易检索信息(请注意,使用新添加的WorkingSite属性,对绑定[“。”]的更改很小):

<ListView ItemsSource="{Binding UserLocations}">
   <ListView.ItemTemplate>
       <DataTemplate>
           <ViewCell>
               <Grid>
                   <Grid.RowDefinitions>
                       <RowDefinition Height="1*" />
                       <RowDefinition Height="1*" />
                       <RowDefinition Height="1*" />
                   </Grid.RowDefinitions>
                   <Grid.ColumnDefinitions>
                       <ColumnDefinition Width="100" />
                       <ColumnDefinition Width="1*" />
                       <ColumnDefinition Width="2*" />
                   </Grid.ColumnDefinitions>
                   <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" />
                   <Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding WorkingSite.Name}" />
                   <Label Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding WorkingSite.Description}" />
                   <Label Grid.Row="2" Grid.Column="1" Text="{Binding Longitude}" />
                   <Label Grid.Row="2" Grid.Column="2" Text="{Timestamp}" HorizontalTextAlignment="End" />
               </Grid>
           </ViewCell>
       </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

希望它对您有帮助并且编码愉快!