Forum Xamarin Xamarin.Forms

Unable to refresh the ListView

zRGzRG PTMember

I've developed a WCF service which is hosted in my localserver. I'm currently being able to consume data from that service in my Xamarin.Forms application. My WCF service is basically some SQL Querys to my local database. I have a ListView that is linked to and ObservableCollection that is updated from my WCF service.

My ListView:

`
<ListView.ItemTemplate>


<ViewCell.View>

           <AbsoluteLayout>
             <Label Text="{Binding Class}"
                    AbsoluteLayout.LayoutBounds="0,10,50,50"
                    Font="Bold, Large"
                    TextColor="Black"
                    BackgroundColor="{Binding Color}"
                    XAlign="Center"
                    YAlign="Center"/>
           </AbsoluteLayout>

          <StackLayout Padding="5, 0, 0, 0"
                       VerticalOptions="Center">

            <Label Text="{Binding AlarmText}"
                   Font="Bold, Medium" />

            <StackLayout
              Orientation="Horizontal"
              Spacing="0">

              <Label Text="{Binding AlarmTime}"/>

            </StackLayout>

          </StackLayout>
        </StackLayout>
      </ViewCell.View>
    </ViewCell>
  </DataTemplate>
</ListView.ItemTemplate>

`

My alarm class:

`public class Alarm
{
public Alarm()
{

    }

    public string Name { get; set; }
    public string Id { get; set; }
    public string Category { get; set; }
    public string Area { get; set; }
    public string Class { get; set; }
    public string Status { get; set; }
    public string AlarmTime { get; set; }
    public string NoOfAlarms { get; set; }
    public string AlarmText { get; set; }
    public string SigType { get; set; }
    public string ActionText { get; set; }
    public string Description { get; set; }
    public Color Color { get; set; }

}`

My Globals class (where the static ObservableCollection that is the ItemsSource of the ListView is stored):

`public class Globals
{
public static string username;
public static ObservableCollection alarms = new ObservableCollection();
public static Color Orange = Color.FromRgb(255, 165, 0);

    public static void fillAlarmsList(List<String> alarmsStringList)
    {
        alarms.Clear();

        for (int i = 0; i < alarmsStringList.Count; i = i + 12)
        {
            Alarm alarm = new Alarm();

            alarm.Name = alarmsStringList.ElementAt(i);
            alarm.Id = alarmsStringList.ElementAt(i + 1);
            alarm.Category = alarmsStringList.ElementAt(i + 2);
            alarm.Area = alarmsStringList.ElementAt(i + 3);
            alarm.Class = alarmsStringList.ElementAt(i + 4);
            alarm.Status = alarmsStringList.ElementAt(i + 5);
            alarm.AlarmTime = alarmsStringList.ElementAt(i + 6);
            alarm.NoOfAlarms = alarmsStringList.ElementAt(i + 7);
            alarm.AlarmText = alarmsStringList.ElementAt(i + 8);
            alarm.SigType = alarmsStringList.ElementAt(i + 9);
            alarm.ActionText = alarmsStringList.ElementAt(i + 10);
            alarm.Description = alarmsStringList.ElementAt(i + 11);

            if (alarm.Class.Equals("A"))
                alarm.Color = Color.Red;
            else if (alarm.Class.Equals("B"))
                alarm.Color = Orange;
            else if (alarm.Class.Equals("C"))
                alarm.Color = Color.Yellow;

            alarms.Add(alarm);
        }
    }
}`

I have a simple MainPage that just has a button that is "Clicked method" calls my SQLClient.getAlarmsAsync(). The SQLClient.getAlarmsCompleted handler gets a List alarmsData and I just call the Globals.fillAlarmsList(alarmsData) and then changes to the page that has my ListView. Until this point, there is no problem, my ListView is populated as it was supposed to. By clicking in any element of the listview, I go to a different contentpage where I can remove that element from the list and when I go back to the contentpage, the listview is updated as it is supposed to.

My problem is that when I am in the listview page, I want the user the able to refresh that list, so I implemented the method -> Refreshing = "OnRefresh".

My problem is that I can't refreh inside this function because the WCF function that I call is an async function and it is handled in the EventHandler:

` void OnRefresh(object sender, EventArgs e)
{
/*var list = (ListView)sender;

        var itemList = alarms.Reverse().ToList();
        alarms.Clear();
        foreach (var s in itemList)
        {
            alarms.Add(s);
        }

        list.IsRefreshing = false;*/

        client.getAlarmsDataByUserAsync(Globals.username);
    }

 private void SQLService_getAlarmsDataByUserCompleted(object sender, getAlarmsDataByUserCompletedEventArgs e)
    {
        Globals.fillAlarmsList(e.Result.ToList());

        Device.BeginInvokeOnMainThread(() =>
        {
            alarmsListView.IsRefreshing = false;
        });
    }

`

When I reach the end of the SQLService_getAlarmsDataByUserCompleted, I have a breakpoint and the "alarmsListView.IsRefreshing = false;" doen't do anything because in the watchList, I checked that the alarmsListView property IsRefrehsing is still true.
I'm kind of a rookie but I thought that when I updated my ObservableCollection, the ListView would be automatically updated, that's why I have an ObservableCollection instead of a List.

I accept any suggestions that allow me to make a refresh of the listview with the only condition being that I want to make that refresh without leaving that page. I realise that I can't change my ObservableColletion outside the main thread because it is the itemsSource of an UI element, that's why I always put the instructions that handle that object inside of the:

Device.BeginInvokeOnMainThread(() =>
{

        });

Any help would be appreciated. Thanks.

Best Answer

Answers

  • FriedSlothFriedSloth DEMember ✭✭
    edited September 2016

    I think you should look a bit into tutorials and demo applications :smile:

    XAlign="Center"
    YAlign="Center"/>
    

    Is deprecated for example.

    You should also avoid stacking StackLayouts, thats not the purpose of them. Use Grids!
    There is a XAML Previewer in alpha available that you can use to design your app btw.: https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-previewer/

    IsRefresh=false;
    You can use yourListView.EndRefresh();

    To your main problem:

    I think your Alarm model should implement INotifyPropertyChanged, look that one up!

    Alternatively you can just use PropertyChanged.Fody which is available at the Nuget browser.

  • zRGzRG PTMember
    edited September 2016

    Konrad, thanks for your quick response. I will try to use grids, and remove the XAlign and YAlign properties are related to this thread that I have created and had no answers:

    https://forums.xamarin.com/discussion/74238/bind-layoutbounds-of-absolutelayout#latest

    I agree 100% with you and I've downloaded some XAMLSamples and view a some tutorials in facebook but it is being hard to view something that can help me, I can't find many things about Xamarin.Forms and I just post something here when I don't know what more to do. I'll try to implement the INotifyPropertyChanged, but I think that would be useful if my alarm propertys changed but that's not the case. The only thing that is changing is my List that is cleared and then populated again, an attribute of an alarm will never change. But may be you're right, I will try that. Thanks in advance, I will try to solve my problem, with your suggestions :)

    (I am currently using Visual Studio so I have never used the previewer, may be I just have to move to xamarin ide..)

  • FriedSlothFriedSloth DEMember ✭✭

    Check out the Xamarin YouTube channel or the channel https://www.youtube.com/user/jamesmontemagno
    You can find some tutorials at the microsoft virtual academy aswell https://mva.microsoft.com/

    If the value of your properties change but the listview does not update NotifyPropertyChanged should help.

    Good luck!

  • zRGzRG PTMember

    Thank you Mabrouk, instead of using what is supposedly more appropriate for an updatable listview, an ObservableCollection (an observableCollection: https://msdn.microsoft.com/en-us/magazine/mt147239.aspx, where it says "(...) Lists that can change during the course of an application should be stored in ObservableCollection instances.
    Such a list raises the CollectionChanged event when its content changes (addition, removal or a different sorting order).(...)"), if I just rebind the itemsSource instead of updating it, it works.

    I know that there is a more elegant way to do this, for sure, but that will work for now. Thanks!

Sign In or Register to comment.