我已经创建了Xamarin形式的ListView并绑定到视图模型中的Observable集合,通过调用OnPropertyChanged事件将项目动态添加到ListView可以正常工作。
但是从服务获取状态更新后,我将更新相应的ListView项目状态并调用OnPropertyChanged事件,并将ListView项目重新关联到该事件,但有时无法正常工作,有时无法正常工作。>
下面是我完成的示例代码。
<ListView Grid.Row="3" HasUnevenRows="True" ItemsSource="{Binding ServiceList}" IsPullToRefreshEnabled="True" SeparatorColor="Black">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Spacing="4" Padding="5" BackgroundColor="LightGray">
<Label Text="{Binding OperationStatus, Converter={x:Static local:StatusMessageConverter.Default}}" FontSize="13" FontAttributes="Bold" TextColor="White" BackgroundColor="DarkCyan" />
<Label Text="{Binding Operation}" FontSize="10" Margin="10,0,0,0" />
<Label Text="{Binding OperationType}" FontSize="10" Margin="10,0,0,0" />
<Label Text="{Binding OperationStatus}" LineBreakMode="WordWrap" IsVisible="{Binding CanStatusVisible}" FontSize="10" Margin="10,0,0,0" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public class ServiceViewModel : INotifyPropertyChanged
{
public ObservableCollection<ServiceItem> ServiceList
{
get
{
return _serviceList;
}
set
{
_serviceList = value;
OnPropertyChanged("ServiceList");
}
}
var tempList = new ObservableCollection<ServiceItem>();
tempList = ServiceList;
var targetItem = from item in tempList
where item.UniqueId == uniqueId
select item;
if (targetItem.Any())
{
var resultItem = targetItem.FirstOrDefault();
resultItem.CanStatusVisible = true;
resultItem.OperationStatus = string.Format("{0}: {1}", "Status Message", resultMessage);
}
ServiceList = null;
ServiceList = tempList;
OnPropertyChanged("ServiceList");
}
public class ServiceItem
{
public string UniqueId { get; set; }
public string Operation { get; set; }
public string OperationType { get; set; }
public string OperationStatus { get; set; }
public string StatusMessage { get; set; }
public bool CanStatusVisible { get; set; }
}
答案 0 :(得分:0)
请确保您的模型类继承自INotifyPropertyChanged
接口(如以上注释中所述)。
public class ServiceItem :INotifyPropertyChanged
{
private string uniqueId,operation,operationType,operationStatus,statusMessage;
private bool statusVisible;
public string UniqueId { get { return uniqueId; } set { uniqueId= value; RaisePropertyChanged(nameof(UniqueId)); } }
public string Operation { get { return operation; } set { operation= value; RaisePropertyChanged(nameof(Operation)); } }
public string OperationType { get { return operationType; } set { operationType= value; RaisePropertyChanged(nameof(OperationType)); } }
public string OperationStatus { get { return operationStatus; } set { operationStatus= value; RaisePropertyChanged(nameof(OperationStatus)); } }
public string StatusMessage { get { return statusMessage; } set { statusMessage= value; RaisePropertyChanged(nameof(StatusMessage)); } }
public bool CanStatusVisible { get { return statusVisible; } set { statusVisible= value; RaisePropertyChanged(nameof(CanStatusVisible )); } }
}
然后,您的ViewModel代码应如下所示:
var tempList = new ObservableCollection<ServiceItem>();
tempList = ServiceList;
var targetItem = from item in tempList
where item.UniqueId == uniqueId
select item;
if (targetItem.Any())
{
var resultItem = targetItem.FirstOrDefault();
resultItem.CanStatusVisible = true;
resultItem.OperationStatus = string.Format("{0}: {1}", "Status Message", resultMessage);
}
ServiceList.Clear();
ServiceList = tempList;
一旦进行了这些更改,您的代码便会正常运行
答案 1 :(得分:0)
---澄清我对FreakyAli的好答案的评论---
FreakyAli回答的关键部分是第一个代码段:
public class ServiceItem :INotifyPropertyChanged
...
完成后,可以极大地简化所讨论的其他代码。我认为(尽管我尚未测试),您可以将 all 代码替换成Ali在下显示的代码:“然后,您的ViewModel代码应如下所示:” 用:
ServiceItem resultItem = ServiceList.Where(item => item.UniqueId == uniqueId).FirstOrDefault();
if (resultItem != null)
{
resultItem.CanStatusVisible = true;
resultItem.OperationStatus = string.Format("{0}: {1}", "Status Message", resultMessage);
}
也就是说,既不必创建临时列表,也不必操纵ServiceList
。当您更改ServiceItem
的属性时,该属性的RaisePropertyChanged
将触发所需的显示刷新。