2017-09-11 14 views
0

レコードを削除したり別のビューからレコードを追加したりすると、Xamarin ListViewをリフレッシュするのに問題があります。Refresh Xamarin ListView on AddまたはDelete

私はViewModelから取得した観測可能なコレクション内のレースを一覧表示するビュー(RaceList.xaml)を持っています。

RaceList.xaml.cs

using System.Collections.Generic; 
using TechsportiseApp.API; 
using TechsportiseApp.API.Models; 
using Xamarin.Forms; 
using Xamarin.Forms.Xaml; 
using TechsportiseApp.MainUI.ViewModels; 
using System; 

namespace TechsportiseApp.MainUI 
{ 
    [XamlCompilation(XamlCompilationOptions.Compile)] 
    public partial class RaceList : ContentPage 
    { 
     public List<Race> Races { get; set; } 

     public RaceList() 
     { 
      InitializeComponent(); 

      var viewModel = new RaceListViewModel(); 
      BindingContext = viewModel; 



      ToolbarItems.Add(new ToolbarItem("New", "Add.png", async() => 
      { 
       await Navigation.PushAsync(new RaceNew()); 
      })); 
     } 

     public void OnDelete(object sender, EventArgs e) 
     { 
      var menuitem = ((MenuItem)sender); 
      var stringraceid = menuitem.CommandParameter.ToString(); 
      int raceid = Int32.Parse(stringraceid); 

      RacesAPI.DeleteRace(raceid); 
      MessagingCenter.Send(this, "RaceListChanged"); 
     } 

     protected override void OnAppearing() 
     { 
      base.OnAppearing(); 
      RacesAPI.GetRaces(); 
      //LoadServerRegisteredCitizen is a method which i used to load items inside the listview   
     } 

     async void Handle_ItemTapped(object sender, Xamarin.Forms.ItemTappedEventArgs e) 
     { 
      if (e.Item == null) 
       return; 
      var race = e.Item as Race; 

      await Navigation.PushAsync(new RaceView(race)); 
      //Deselect Item 
      ((ListView)sender).SelectedItem = null; 
     } 


    } 
} 

RaceList.xaml

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      x:Class="TechsportiseApp.MainUI.RaceList" 
      Title="Races"> 
    <!--SelectedItem="{Binding RaceSelected, Mode=TwoWay} "--> 
    <ListView ItemsSource="{Binding Races}" 
     ItemTapped="Handle_ItemTapped" 
     SeparatorVisibility = "None" 
     IsPullToRefreshEnabled="true" 
     RefreshCommand="{Binding RefreshCommand}" 
     IsRefreshing="{Binding IsBusy}"> 

     <ListView.ItemTemplate> 
      <DataTemplate> 
       <ViewCell> 
        <ViewCell.ContextActions> 
         <MenuItem Clicked="OnDelete" CommandParameter="{Binding Id}" Text="Delete" IsDestructive="True" /> 
        </ViewCell.ContextActions> 
        <StackLayout> 
         <Label Text="{Binding Name}" /> 
         <Label Text="{Binding RaceDate}" /> 
         <BoxView Color="#B2B2B2" HeightRequest="1" /> 
        </StackLayout> 
       </ViewCell> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
</ContentPage> 

RaceListViewModel.cs

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Threading.Tasks; 
using Newtonsoft.Json; 
using RestSharp; 
using TechsportiseApp.API.Models; 
using Xamarin.Forms; 
using TechsportiseApp.API; 
using System.Windows.Input; 
using System.Collections.ObjectModel; 

namespace TechsportiseApp.MainUI.ViewModels 
{ 
    public class RaceListViewModel : INotifyPropertyChanged 
    { 
     public RaceListViewModel() 
     { 
      _refreshCommand = new Command(RefreshList); 

      MessagingCenter.Subscribe<RaceListViewModel>(this, "RaceListChanged", sender => { 
       Races = RacesAPI.GetRaces(); 
       OnPropertyChanged("Id"); 
      }); 
     } 

     public void RefreshList() 
     { 
      //Refreshes list on Pull to Refresh 
      Races = RacesAPI.GetRaces(); 
     } 

     int _id; 
     public int Id 
     { 
      get 
      { 
       return _id; 
      } 
      set 
      { 
       if (_id != value) 
       { 
        _id = value; 
        // trigger some action to take such as updating other labels or fields 
        OnPropertyChanged("Id"); 
       } 
      } 
     } 

     int _name; 
     public int Name 
     { 
      get 
      { 
       return _name; 
      } 
      set 
      { 
       if (_name != value) 
       { 
        _name = value; 

        // trigger some action to take such as updating other labels or fields 
        OnPropertyChanged("Name"); 
       } 
      } 
     } 

     private ObservableCollection<Race> _races; 
     public ObservableCollection<Race> Races 
     { 
      get 
      { 
       var racelist = RacesAPI.GetRaces(); 
       IsBusy = false; 
       return racelist; 
      } 
      set 
      { 
       if (_races != value) 
       { 
        _races = value; 
        // trigger some action to take such as updating other labels or fields 
        OnPropertyChanged("Races"); 
       } 
      } 
     } 

     private Race _raceSelected; 
     public Race RaceSelected 
     { 
      get 
      { 
       return RaceSelected; 
      } 
      set 
      { 
       if (RaceSelected != value) 
       { 
        RaceSelected = value; 
        OnPropertyChanged("RaceSelected"); 
       } 
      } 
     } 



     private bool _isBusy; 
     public bool IsBusy 
     { 
      get { return _isBusy; } 
      set 
      { 
       if (_isBusy == value) 
        return; 

       _isBusy = value; 
       OnPropertyChanged("IsBusy"); 
      } 
     } 



     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      var changed = PropertyChanged; 
      if (changed != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     Command _refreshCommand; 
     public Command RefreshCommand 
     { 
      get 
      { 
       return _refreshCommand; 
      } 
     } 
    } 
} 

ツールバーの「作成」ボタンを押すと、新しいレースのデータを記入できる空白のフォームが表示されます。これを保存するとJSONがAPIにプッシュされ、成功した場合はJSONが編集ページにリダイレクトされます。

RaceNew.xaml

<?xml version="1.0" encoding="UTF-8"?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      xmlns:sys="clr-namespace:System;assembly=mscorlib" 
      x:Class="TechsportiseApp.MainUI.RaceNew" 
      Title="New Race"> 
    <ContentPage.Content> 
    <ScrollView Orientation = "Vertical" VerticalOptions="StartAndExpand"> 
    <StackLayout Padding="0,20,0,0"> 
     <Label x:Name="labelName" Text="Name" /> 
      <Entry x:Name="entryName" /> 
     <Label x:Name="labelDescription" Text="Description" /> 
      <Editor x:Name="editorDescription" /> 
     <Label x:Name="labelContactName" Text="Contact Name" /> 
      <Entry x:Name="entryContactName" /> 
     <Label x:Name="labelContactNumber" Text="Contact Number" /> 
      <Entry x:Name="entryContactNumber" Keyboard="Telephone" /> 
     <Label x:Name="labelContactEmail" Text="ContactEmail" /> 
      <Entry x:Name="entryContactEmail" Keyboard="Email" /> 
     <Label x:Name="labelRaceDate" Text="Race Date" /> 
       <DatePicker x:Name="datepickerRaceDate" Date="{Binding Source={x:Static sys:DateTime.Now}" Format="ddd d MMMM yyyy" /> 
     <Label x:Name="labelRaceStartTime" Text="Race Time" /> 
       <TimePicker x:Name="timepickerRaceStartTime" /> 
     <Label x:Name="labelMaxEntries" Text="Max Entries" /> 
       <Entry x:Name="entryMaxEntries" Keyboard="Numeric" /> 
     <Label x:Name="labelCurrentEntries" Text="Current Entries" /> 
       <Entry x:Name="entryCurrentEntries" Keyboard="Numeric" /> 
     <Label x:Name="labelIsOpenForEntries" Text="Open For Entries" /> 
      <Switch x:Name="switchIsOpenForEntries" /> 
     <Label x:Name="labelIsPublished" Text="Published" /> 
      <Switch x:Name="switchIsPublished" />   
    </StackLayout> 
    </ScrollView> 
    </ContentPage.Content> 
</ContentPage> 

RaceNew.xaml.cs

using System; 
using TechsportiseApp.API; 
using TechsportiseApp.API.Models; 
using Xamarin.Forms; 
using Xamarin.Forms.Xaml; 

namespace TechsportiseApp.MainUI 
{ 
    [XamlCompilation(XamlCompilationOptions.Compile)] 
    public partial class RaceNew : ContentPage 
    { 
     public RaceNew() 
     { 
      InitializeComponent(); 

      ToolbarItems.Add(new ToolbarItem("Create", "", async() => 

      { 
       var saverace = new Race(); 
       saverace.ContactEmail = entryContactEmail.Text; 
       saverace.ContactName = entryContactName.Text; 
       saverace.ContactNumber = entryContactNumber.Text; 
       saverace.CurrentEntries = 0; 
       saverace.Description = editorDescription.Text; 
       saverace.IsOpenForEntries = switchIsOpenForEntries.IsToggled; 
       saverace.IsPublished = switchIsPublished.IsToggled; 
       saverace.IsComplete = false; 
       saverace.MaxEntries = System.Convert.ToInt32(entryMaxEntries.Text); 
       saverace.Name = entryName.Text; 
       saverace.RaceDate = datepickerRaceDate.Date; 

       var timestring = string.Format("{0:00}:{1:00}:{2:00}", timepickerRaceStartTime.Time.Hours, timepickerRaceStartTime.Time.Minutes, timepickerRaceStartTime.Time.Seconds); 
       saverace.RaceStartTime = timestring; 

       var response = RacesAPI.CreateRace(saverace); 
       if (response.Code == "Created") 
       { 
        saverace.Id = response.ReturnedId; 
        Navigation.InsertPageBefore(new RaceView(saverace), this); 
        await Navigation.PopAsync(); 

       } 
       //Error response 
       else 
       { 
        await DisplayAlert("Error: " + response.Code, "There has been an error creating your race. " + response.Content, "OK"); 
       } 
      })); 
     } 


     async void OnBackButtonClicked(object sender, EventArgs e) 
     { 
      await Navigation.PopAsync(); 
     } 
    } 
} 

このページから、私は単純に[戻る]ボタンを押すと、それは戻って私のRaceListビューに私を返します。

問題は、リストビューがリフレッシュされないことです。新しいレースが追加されたことを登録しません。

また、私のRaceList.xaml.csには、使用中の削除ボタンもあります。リストから項目を削除すると、項目が更新されません。

アイデア?

+0

あなたはOC のインスタンスにバインドしていますが、更新または更新するたびに、バインドされているインスタンスを更新する代わりに、新しいインスタンスOC が返されます。これは、OCを使用する目的を実際に破ります。 – Jason

+0

私はもともとListを使用していましたが、ListViewをリフレッシュするためにさまざまな方法を試しているので、多分おそらく冗長コードがたくさんあります。 私がしたいことは、トリックを行うと思うが、それを行う方法を考えることができないと、ページ全体に拘束されたビューモデルを共有することです。 –

答えて

1

Xamarin.Forms.Page.OnAppearingメソッドをオーバーライドし、ViewModelのRefreshList()メソッドを呼び出します。

RacelistViewModel Viewmodel =(RaceListViewModel)This.DataContext; ViewModel.RefreshList();

+0

これはほとんどそれでした...それを修正するために軽いタイプミス。ありがとう! RaceListViewModelビューモデル=(RaceListViewModel)this.BindingContext。 Viewmodel.RefreshList(); –

0

私は知らないが、

public List<Race> Races { get; set; } 

List、ないObservableCollectionです。

+0

彼は彼のVMにを持っています – Jason