Xamarin 表单:如何从列表视图中隐藏重复的月份名称?
Xamarin forms: How to hide the repeated month name from the listview?
我的应用程序中有一个事件列表(UI-1,左侧屏幕),月份名称总是重复。
我需要从列表中删除重复的月份名称,并且需要一个 UI,例如 UI-2(右侧)。
我正在为此功能使用列表视图,以下是我的代码:
就我而言,我需要按月顺序显示我的列表。我在下面添加了我当前的代码:
我的模型Class:
public class CalendarEvents
{
public List<EventsHB> eventsHB { get; set; }
}
public class EventsHB
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
public class EventTO
{
public string calendarEventId { get; set; }
public string title { get; set; }
public long startDate { get; set; }
public string startTime { get; set; }
}
我的 JSON 回复:
"eventsHB": [
{
"eventTO": {
"calendarEventId": 136,
"title": " school event",
"startDate": 1561006800000,
"startTime": "6:15 PM"
},
"month": "July"
},
{
"eventTO": {
"calendarEventId": 139,
"title": "New Admission Day"
"startDate": 1560834000000
"startTime": "10:00 AM"
},
"month": "July"
},
{
"eventTO": {
"calenderId": 810354,
"title": "event pta"
"startDate": 1559710800000,
"startTime": "10:00 AM"
},
"month": "June"
},
{
"eventTO": {
"calendarEventId": 89,
"title": "Memorial Day Meet",
"startDate": 1559365200000,
"startTime": "8:00 AM"
},
"month": "June"
}
]
Xaml:
<ListView x:Name="MyEventsListview"
HasUnevenRows="True"
ItemsSource="{Binding AllItems,Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout
Orientation="Vertical">
<Label
Text="{Binding month}"/>
<StackLayout
Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<StackLayout
Grid.Column="0"
Orientation="Vertical">
<Label
Text="{Binding eventTO.startDate, Converter={StaticResource dayConverter}}"/>
<Label
Text="{Binding eventTO.startDate, Converter={StaticResource dateConverter}}"/>
<Label
Text="{Binding eventTO.startTime}"/>
</StackLayout>
<Label
Text="{Binding eventTO.title}"/>
</Grid>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
视图模型:
HttpClient client = new HttpClient();
var Response = await client.GetAsync("My REST Call");
if (Response.IsSuccessStatusCode)
{
string response = await Response.Content.ReadAsStringAsync();
myevents = new CalendarEvents();
if (response != "")
{
myevents = JsonConvert.DeserializeObject<CalendarEvents>(response.ToString());
}
AllItems = new ObservableCollection<EventsHB>(myevents.eventsHB);
我不知道需要对模型 class、xaml 和 ViewModel 进行哪些更改才能在月视图中对列表进行分组。谁能提出解决方案提示?
您需要按月对 ListView 进行分组。 ListView提供了一个名为"IsGroupingEnabled"的属性,你需要设置为True。
那么需要对ListView的GroupHeaderTemplate进行如下设置:
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell Height="45">
<Grid Padding="10" BackgroundColor="WhiteSmoke">
<Label Text="{Binding Key}" FontSize="18"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
回顾一下我的简单分组Xaml Page and ViewModel
在我的示例中,我按类别分组,但在您的情况下,您应该将月份设置为组键。
你可以试试我的整个样本 Github
我为您编写了一个示例,以展示在您的案例中显示分组 ListView 应该具有的模型和数据:
模型和数据应该是这样的:
public partial class MainPage : ContentPage
{
public ObservableCollection<EventsHB> AllItems { get; set; }
public MainPage()
{
InitializeComponent();
AllItems = new ObservableCollection<EventsHB>();
var julyGroup = new EventsHB() {month = "july"};
julyGroup.Add(new EventTO() { calendarEventId = "1", title = "firstTitle", startDate = "01-1-1", startTime = "01-1-1"});
julyGroup.Add(new EventTO() { calendarEventId = "2", title = "secondTitle", startDate = "02-1-1", startTime = "01-1-2" });
julyGroup.Add(new EventTO() { calendarEventId = "3", title = "thirdTitle", startDate = "02-1-1", startTime = "01-1-3" });
julyGroup.Add(new EventTO() { calendarEventId = "4", title = "fourthTitle", startDate = "02-1-1", startTime = "01-1-4" });
var juneGroup = new EventsHB() { month = "june" };
juneGroup.Add(new EventTO() { calendarEventId = "1", title = "junefirstTitle", startDate = "01-1-1", startTime = "01-1-1" });
juneGroup.Add(new EventTO() { calendarEventId = "2", title = "junesecondTitle", startDate = "02-1-1", startTime = "01-1-2" });
juneGroup.Add(new EventTO() { calendarEventId = "3", title = "junethirdTitle", startDate = "02-1-1", startTime = "01-1-3" });
juneGroup.Add(new EventTO() { calendarEventId = "4", title = "junefourthTitle", startDate = "02-1-1", startTime = "01-1-4" });
AllItems.Add(julyGroup);
AllItems.Add(juneGroup);
//...
//more months like April,May can be added
BindingContext = this;
}
}
public class EventsHB : ObservableCollection<EventTO>
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
public class EventTO
{
public string calendarEventId { get; set; }
public string title { get; set; }
public string startDate { get; set; }
public string startTime { get; set; }
}
而且在你的json数据中,数据结构似乎不符合我在示例中列出的结构,所以你要做的是将你的数据转换为正确的结构,我写了一个测试函数你可以检查它是否有效:
//A test function to convert you json array to the array we need
void test()
{
EventsHB julyGroup = new EventsHB() { month = "july" }; ;
EventsHB juneGroup = new EventsHB() { month = "june" };
//other months group
foreach (var item in AllItems)
{
EventsHB hb = item;
if (hb.month == "july")
{
julyGroup.Add(hb.eventTO);
}
else if (hb.month == "june")
{
juneGroup.Add(hb.eventTO);
}//...other months
}
//at last, add them to All items.
AllItems.Add(julyGroup);
AllItems.Add(juneGroup);
//...add other months
}
您可以按照自己的方式进行转换。
样本在这里:grouped-listView
参考:customizing-list-appearance#grouping
更新:
在应用程序端转换数据结构真的很复杂,我为您转换它并在项目中更新代码的每个地方添加注释。
你得到异常的原因是因为模型EventsHB : ObservableCollection<EventTO>
,所以我在这里创建一个新的来反序列化json。
public class CalendarEvents
{
//update here: here should be List<EventsHBTwo>
public List<EventsHBTwo> eventsHB { get; set; }
}
//update use this one to shou grouped list data
public class EventsHB : ObservableCollection<EventTO>
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
//Update: use this one to deserialize json
public class EventsHBTwo
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
在ViewModel.cs中:
//Update: add a new tempItem to get json data
public ObservableCollection<EventsHBTwo> tempItem
{
get
{
return _tempItems;
}
set
{
_tempItems = value;
OnPropertyChanged("tempItem");
}
}
然后使用此 tempItem 获取 json 数据:
tempItem = new ObservableCollection<EventsHBTwo>(myevents.eventsHB);
//update: converData here
converData(tempItem);
转换函数:
public void converData(ObservableCollection<EventsHBTwo> allItem)
{
AllItems = new ObservableCollection<EventsHB>();
EventsHB julyGroup = new EventsHB() { month = "July" };
EventsHB juneGroup = new EventsHB() { month = "June" };
foreach (var item in allItem)
{
EventsHBTwo hb = item;
if (hb.month == "July")
{
julyGroup.Add(hb.eventTO);
}
else if (hb.month == "June")
{
juneGroup.Add(hb.eventTO);
}
}
//at last, add them to All items.
AllItems.Add(julyGroup);
AllItems.Add(juneGroup);
}
在 xaml 的最后,在此处添加 IsGroupingEnabled GroupShortNameBinding GroupDisplayBinding:
<ListView x:Name="MyEventsListview"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"
IsPullToRefreshEnabled="True"
HasUnevenRows="True"
ItemsSource="{Binding AllItems,Mode=TwoWay}"
BackgroundColor="White"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding month}"
GroupShortNameBinding="{Binding month}">
并直接使用startDate startTime代替eventTO.startDate。
我在这里上传了我的样本,你可以查看:working-grouped-listView-xamarin.forms
实现此目的的最佳方法是让您的服务端像这样给您json:
{"eventsHB":
{july:[
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
}
{june:[
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
]
}
...
}
我的应用程序中有一个事件列表(UI-1,左侧屏幕),月份名称总是重复。
我需要从列表中删除重复的月份名称,并且需要一个 UI,例如 UI-2(右侧)。
我正在为此功能使用列表视图,以下是我的代码:
就我而言,我需要按月顺序显示我的列表。我在下面添加了我当前的代码:
我的模型Class:
public class CalendarEvents
{
public List<EventsHB> eventsHB { get; set; }
}
public class EventsHB
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
public class EventTO
{
public string calendarEventId { get; set; }
public string title { get; set; }
public long startDate { get; set; }
public string startTime { get; set; }
}
我的 JSON 回复:
"eventsHB": [
{
"eventTO": {
"calendarEventId": 136,
"title": " school event",
"startDate": 1561006800000,
"startTime": "6:15 PM"
},
"month": "July"
},
{
"eventTO": {
"calendarEventId": 139,
"title": "New Admission Day"
"startDate": 1560834000000
"startTime": "10:00 AM"
},
"month": "July"
},
{
"eventTO": {
"calenderId": 810354,
"title": "event pta"
"startDate": 1559710800000,
"startTime": "10:00 AM"
},
"month": "June"
},
{
"eventTO": {
"calendarEventId": 89,
"title": "Memorial Day Meet",
"startDate": 1559365200000,
"startTime": "8:00 AM"
},
"month": "June"
}
]
Xaml:
<ListView x:Name="MyEventsListview"
HasUnevenRows="True"
ItemsSource="{Binding AllItems,Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout
Orientation="Vertical">
<Label
Text="{Binding month}"/>
<StackLayout
Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<StackLayout
Grid.Column="0"
Orientation="Vertical">
<Label
Text="{Binding eventTO.startDate, Converter={StaticResource dayConverter}}"/>
<Label
Text="{Binding eventTO.startDate, Converter={StaticResource dateConverter}}"/>
<Label
Text="{Binding eventTO.startTime}"/>
</StackLayout>
<Label
Text="{Binding eventTO.title}"/>
</Grid>
</StackLayout>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
视图模型:
HttpClient client = new HttpClient();
var Response = await client.GetAsync("My REST Call");
if (Response.IsSuccessStatusCode)
{
string response = await Response.Content.ReadAsStringAsync();
myevents = new CalendarEvents();
if (response != "")
{
myevents = JsonConvert.DeserializeObject<CalendarEvents>(response.ToString());
}
AllItems = new ObservableCollection<EventsHB>(myevents.eventsHB);
我不知道需要对模型 class、xaml 和 ViewModel 进行哪些更改才能在月视图中对列表进行分组。谁能提出解决方案提示?
您需要按月对 ListView 进行分组。 ListView提供了一个名为"IsGroupingEnabled"的属性,你需要设置为True。
那么需要对ListView的GroupHeaderTemplate进行如下设置:
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell Height="45">
<Grid Padding="10" BackgroundColor="WhiteSmoke">
<Label Text="{Binding Key}" FontSize="18"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
回顾一下我的简单分组Xaml Page and ViewModel
在我的示例中,我按类别分组,但在您的情况下,您应该将月份设置为组键。
你可以试试我的整个样本 Github
我为您编写了一个示例,以展示在您的案例中显示分组 ListView 应该具有的模型和数据:
模型和数据应该是这样的:
public partial class MainPage : ContentPage
{
public ObservableCollection<EventsHB> AllItems { get; set; }
public MainPage()
{
InitializeComponent();
AllItems = new ObservableCollection<EventsHB>();
var julyGroup = new EventsHB() {month = "july"};
julyGroup.Add(new EventTO() { calendarEventId = "1", title = "firstTitle", startDate = "01-1-1", startTime = "01-1-1"});
julyGroup.Add(new EventTO() { calendarEventId = "2", title = "secondTitle", startDate = "02-1-1", startTime = "01-1-2" });
julyGroup.Add(new EventTO() { calendarEventId = "3", title = "thirdTitle", startDate = "02-1-1", startTime = "01-1-3" });
julyGroup.Add(new EventTO() { calendarEventId = "4", title = "fourthTitle", startDate = "02-1-1", startTime = "01-1-4" });
var juneGroup = new EventsHB() { month = "june" };
juneGroup.Add(new EventTO() { calendarEventId = "1", title = "junefirstTitle", startDate = "01-1-1", startTime = "01-1-1" });
juneGroup.Add(new EventTO() { calendarEventId = "2", title = "junesecondTitle", startDate = "02-1-1", startTime = "01-1-2" });
juneGroup.Add(new EventTO() { calendarEventId = "3", title = "junethirdTitle", startDate = "02-1-1", startTime = "01-1-3" });
juneGroup.Add(new EventTO() { calendarEventId = "4", title = "junefourthTitle", startDate = "02-1-1", startTime = "01-1-4" });
AllItems.Add(julyGroup);
AllItems.Add(juneGroup);
//...
//more months like April,May can be added
BindingContext = this;
}
}
public class EventsHB : ObservableCollection<EventTO>
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
public class EventTO
{
public string calendarEventId { get; set; }
public string title { get; set; }
public string startDate { get; set; }
public string startTime { get; set; }
}
而且在你的json数据中,数据结构似乎不符合我在示例中列出的结构,所以你要做的是将你的数据转换为正确的结构,我写了一个测试函数你可以检查它是否有效:
//A test function to convert you json array to the array we need
void test()
{
EventsHB julyGroup = new EventsHB() { month = "july" }; ;
EventsHB juneGroup = new EventsHB() { month = "june" };
//other months group
foreach (var item in AllItems)
{
EventsHB hb = item;
if (hb.month == "july")
{
julyGroup.Add(hb.eventTO);
}
else if (hb.month == "june")
{
juneGroup.Add(hb.eventTO);
}//...other months
}
//at last, add them to All items.
AllItems.Add(julyGroup);
AllItems.Add(juneGroup);
//...add other months
}
您可以按照自己的方式进行转换。
样本在这里:grouped-listView
参考:customizing-list-appearance#grouping
更新:
在应用程序端转换数据结构真的很复杂,我为您转换它并在项目中更新代码的每个地方添加注释。
你得到异常的原因是因为模型EventsHB : ObservableCollection<EventTO>
,所以我在这里创建一个新的来反序列化json。
public class CalendarEvents
{
//update here: here should be List<EventsHBTwo>
public List<EventsHBTwo> eventsHB { get; set; }
}
//update use this one to shou grouped list data
public class EventsHB : ObservableCollection<EventTO>
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
//Update: use this one to deserialize json
public class EventsHBTwo
{
public string month { get; set; }
public EventTO eventTO { get; set; }
}
在ViewModel.cs中:
//Update: add a new tempItem to get json data
public ObservableCollection<EventsHBTwo> tempItem
{
get
{
return _tempItems;
}
set
{
_tempItems = value;
OnPropertyChanged("tempItem");
}
}
然后使用此 tempItem 获取 json 数据:
tempItem = new ObservableCollection<EventsHBTwo>(myevents.eventsHB);
//update: converData here
converData(tempItem);
转换函数:
public void converData(ObservableCollection<EventsHBTwo> allItem)
{
AllItems = new ObservableCollection<EventsHB>();
EventsHB julyGroup = new EventsHB() { month = "July" };
EventsHB juneGroup = new EventsHB() { month = "June" };
foreach (var item in allItem)
{
EventsHBTwo hb = item;
if (hb.month == "July")
{
julyGroup.Add(hb.eventTO);
}
else if (hb.month == "June")
{
juneGroup.Add(hb.eventTO);
}
}
//at last, add them to All items.
AllItems.Add(julyGroup);
AllItems.Add(juneGroup);
}
在 xaml 的最后,在此处添加 IsGroupingEnabled GroupShortNameBinding GroupDisplayBinding:
<ListView x:Name="MyEventsListview"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"
IsPullToRefreshEnabled="True"
HasUnevenRows="True"
ItemsSource="{Binding AllItems,Mode=TwoWay}"
BackgroundColor="White"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding month}"
GroupShortNameBinding="{Binding month}">
并直接使用startDate startTime代替eventTO.startDate。
我在这里上传了我的样本,你可以查看:working-grouped-listView-xamarin.forms
实现此目的的最佳方法是让您的服务端像这样给您json:
{"eventsHB":
{july:[
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
}
{june:[
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
{"eventTO":{"calendarEventId":135,}}
]
}
...
}