自定义 ListView 绑定在 Xamarin.Forms 中不起作用
Custom ListView binding not working in Xamarin.Forms
我正在尝试将响应绑定到 Xamarin.Forms 中的自定义 ListView,但即使 ObservableCollection 包含结果,ListView 仍为空白。请指出我在下面代码中的错误。
在下面的代码中,我试图实现以下结果 -
- 从 Firebase 收到的响应被序列化,然后根据响应创建自定义日历。
- 为了创建日历,我使用了一个模型,它将包含要在视图中显示的所有必要绑定。例如颜色、标题、计数等
我正在使用 Prism MVVM 架构构建应用程序。
查看
<ListView ItemsSource="{Binding ListItems}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame BorderColor="LightGray" Padding="5">
<StackLayout Orientation="Horizontal">
<!--<BoxView BackgroundColor="{Binding HighlightColor}" WidthRequest="10"/>-->
<Label Text="{Binding Date}" FontSize="Medium" Margin="20,0,0,0"/>
<Label Text="{Binding Day}" FontSize="Medium" Margin="20,0,0,0"/>
<Label Text="{Binding LeaveCount}" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End"/>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel
public ObservableCollection<CalendarItem> ListItems { get; set; }
public LeaveViewerPageViewModel(INavigationService navigationService, IFirebaseService firebaseService)
: base(navigationService, firebaseService)
{
Title = "View Leaves";
ViewCommand = new DelegateCommand(ViewLeaves);
}
private async void ViewLeaves()
{
ListItems = new ObservableCollection<CalendarItem>();
var x = await FirebaseService.GetAll(_month, _year);
foreach (var item in x)
{
ListItems.Add(item);
}
}
服务
public async Task<List<CalendarItem>> GetAll( string month, string year)
{
List<CalendarItem> ItemList = new List<CalendarItem>();
int iterationLimit = DateTime.DaysInMonth(int.Parse(year), (DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture)).Month);
for (int i = 1; i <= iterationLimit; i++)
{
CalendarItem ITEM = new CalendarItem();
DateTime dateTime = new DateTime(int.Parse(year), DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture).Month, i);
var res = await GetLeavesAsync(i, month, year);
ITEM.Date = dateTime.Day.ToString();
ITEM.Day = dateTime.DayOfWeek.ToString();
ITEM.LeaveCount = res.Count;
ITEM.Leaves = res;
if (res.Count > 0)
ITEM.HighlightColor = res.Count < 5 ? System.Drawing.Color.Yellow : System.Drawing.Color.Tomato;
ItemList.Add(ITEM);
}
return ItemList;
}
型号
public class CalendarItem
{
public Color HighlightColor { get; set; }
public string Date { get; set; }
public string Day { get; set; }
public int LeaveCount { get; set; }
public List<LeaveDetail> Leaves { get; set; }
}
根据你这里的代码,实际上有几个问题:
1) ViewModel 中的 ListItems 属性 本身并未实现 INotifyPropertyChanged。
public class ViewAViewModel : BindableBase
{
private ObservableCollection<CalendarItem> _listItems;
public ObservableCollection<CalendarItem> ListItems
{
get => _listItems;
set => SetProperty(ref _listItems, value);
}
}
2) 您正在 ViewLeaves 方法中新建一个 ListItems,然后一次添加一个项目。这里的结果是,如果您在设置 ListItems 时遵循第一步,它会尝试更新 UI,然后每次添加项目时,它都会尝试更新 UI.
3) 您有两种优化方法:
- 使用 James Montemagno 在他的 MvvmHelpers 库中的
ObservableRangeCollection
。这将允许您在 ctor 中更新集合,然后简单地转储一个集合,如:
private async void ViewLeaves()
{
ListItems.ReplaceRange(await FirebaseService.GetAll(_month, _year));
}
- 简单地实现 属性,如我指出的第一期中所示,但将其更改为
IEnumerable<CalendarItem>
并简单地设置为:
private async void ViewLeaves()
{
ListItems = await FirebaseService.GetAll(_month, _year);
}
请尝试按如下方式修改您的列表项:-
private ObservableCollection<CalendarItem> _listItems = new ObservableCollection<CalendarItem>();
public ObservableCollection<CalendarItem> ListItems
{
get => _listItems;
set => SetProperty(ref _listItems, value);
}
我正在尝试将响应绑定到 Xamarin.Forms 中的自定义 ListView,但即使 ObservableCollection 包含结果,ListView 仍为空白。请指出我在下面代码中的错误。
在下面的代码中,我试图实现以下结果 -
- 从 Firebase 收到的响应被序列化,然后根据响应创建自定义日历。
- 为了创建日历,我使用了一个模型,它将包含要在视图中显示的所有必要绑定。例如颜色、标题、计数等
我正在使用 Prism MVVM 架构构建应用程序。
查看
<ListView ItemsSource="{Binding ListItems}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame BorderColor="LightGray" Padding="5">
<StackLayout Orientation="Horizontal">
<!--<BoxView BackgroundColor="{Binding HighlightColor}" WidthRequest="10"/>-->
<Label Text="{Binding Date}" FontSize="Medium" Margin="20,0,0,0"/>
<Label Text="{Binding Day}" FontSize="Medium" Margin="20,0,0,0"/>
<Label Text="{Binding LeaveCount}" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End"/>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel
public ObservableCollection<CalendarItem> ListItems { get; set; }
public LeaveViewerPageViewModel(INavigationService navigationService, IFirebaseService firebaseService)
: base(navigationService, firebaseService)
{
Title = "View Leaves";
ViewCommand = new DelegateCommand(ViewLeaves);
}
private async void ViewLeaves()
{
ListItems = new ObservableCollection<CalendarItem>();
var x = await FirebaseService.GetAll(_month, _year);
foreach (var item in x)
{
ListItems.Add(item);
}
}
服务
public async Task<List<CalendarItem>> GetAll( string month, string year)
{
List<CalendarItem> ItemList = new List<CalendarItem>();
int iterationLimit = DateTime.DaysInMonth(int.Parse(year), (DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture)).Month);
for (int i = 1; i <= iterationLimit; i++)
{
CalendarItem ITEM = new CalendarItem();
DateTime dateTime = new DateTime(int.Parse(year), DateTime.ParseExact(month.Substring(0, 3), "MMM", CultureInfo.InvariantCulture).Month, i);
var res = await GetLeavesAsync(i, month, year);
ITEM.Date = dateTime.Day.ToString();
ITEM.Day = dateTime.DayOfWeek.ToString();
ITEM.LeaveCount = res.Count;
ITEM.Leaves = res;
if (res.Count > 0)
ITEM.HighlightColor = res.Count < 5 ? System.Drawing.Color.Yellow : System.Drawing.Color.Tomato;
ItemList.Add(ITEM);
}
return ItemList;
}
型号
public class CalendarItem
{
public Color HighlightColor { get; set; }
public string Date { get; set; }
public string Day { get; set; }
public int LeaveCount { get; set; }
public List<LeaveDetail> Leaves { get; set; }
}
根据你这里的代码,实际上有几个问题:
1) ViewModel 中的 ListItems 属性 本身并未实现 INotifyPropertyChanged。
public class ViewAViewModel : BindableBase
{
private ObservableCollection<CalendarItem> _listItems;
public ObservableCollection<CalendarItem> ListItems
{
get => _listItems;
set => SetProperty(ref _listItems, value);
}
}
2) 您正在 ViewLeaves 方法中新建一个 ListItems,然后一次添加一个项目。这里的结果是,如果您在设置 ListItems 时遵循第一步,它会尝试更新 UI,然后每次添加项目时,它都会尝试更新 UI.
3) 您有两种优化方法:
- 使用 James Montemagno 在他的 MvvmHelpers 库中的
ObservableRangeCollection
。这将允许您在 ctor 中更新集合,然后简单地转储一个集合,如:
private async void ViewLeaves()
{
ListItems.ReplaceRange(await FirebaseService.GetAll(_month, _year));
}
- 简单地实现 属性,如我指出的第一期中所示,但将其更改为
IEnumerable<CalendarItem>
并简单地设置为:
private async void ViewLeaves()
{
ListItems = await FirebaseService.GetAll(_month, _year);
}
请尝试按如下方式修改您的列表项:-
private ObservableCollection<CalendarItem> _listItems = new ObservableCollection<CalendarItem>();
public ObservableCollection<CalendarItem> ListItems
{
get => _listItems;
set => SetProperty(ref _listItems, value);
}