Xamarin将ListView项目动态更新为GUI

时间:2019-02-06 16:16:14

标签: c# listview xamarin xamarin.forms

我已经创建了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; }
}

2 个答案:

答案 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将触发所需的显示刷新。