Saya memiliki masalah yang sangat aneh dengan cakupan variabel. Tampilan Daftar bernama "TodoListView" ditentukan melalui xaml, dan ItemSource diisi dari database SQListe. Bekerja. Di dalam ListView saya memiliki ViewCell untuk menampilkan data berdasarkan baris.
<ContentPage ... x:Class="JanitorPro.MainPage" ...>
<StackLayout>
<ListView x:Name="TodoListView" Margin="20" ItemSelected="OnListItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Label Text="{Binding name}" VerticalTextAlignment="Center" HorizontalOptions="StartAndExpand" />
<Switch HorizontalOptions="End" IsToggled="{Binding done}" Toggled="DoneSwitchToggled"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
The codebehind looks like this (some irrelevant portions removed):
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
protected override async void OnAppearing()
{
base.OnAppearing();
// load Database
TodoListView.ItemsSource = await App.TodoDatabase.GetItemsAsync("SELECT * FROM [TodoItem]");
}
async void OnReloadButtonClicked(object sender, EventArgs e)
{
Debug.WriteLine("Reload Button Click");
TodoListView.ItemsSource = await App.TodoDatabase.GetItemsAsync("SELECT * FROM [TodoItem]");
Debug.WriteLine("Reload done.");
}
async void OnListItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem != null)
{
await Navigation.PushAsync(new TodoItemPage
{
BindingContext = e.SelectedItem as TodoItem
});
}
}
private void DoneSwitchToggled(object sender, ToggledEventArgs e)
{
// TodoItem i = null;
TodoItem i = TodoListView.SelectedItem;
if (i != null)
{
Debug.WriteLine("Toggle: {0}", i.id);
}
}
}
}
Keanehannya memiliki dua tahap. Sebelum saya memasukkan event handler DoneSwitchToggled, setiap kemunculan TodoListView.ItemsSource mendapat garis bawah merah di bawah TodoListView dan petunjuk bahwa "Nama TodoListView tidak ada dalam konteks saat ini". Oke, saya pikir VS tidak cukup pintar untuk menemukan definisi di file xaml, karena meskipun ada peringatan, program dikompilasi dan berjalan dengan baik. TodoListView diinisialisasi dan menampilkan baris database yang mendasarinya dengan benar, sehingga jelas ada saat runtime.
Segalanya menjadi liar ketika saya menambahkan event handler DoneSwitchToggled ke XAML dan kode di belakang. Tiba-tiba program tidak dapat dikompilasi lagi tetapi keluar dengan kesalahan CS0103 "Nama" TodoListView "tidak ada dalam konteks saat ini". Kesalahan muncul tiga kali, dengan nomor baris menunjuk ke kemunculan TodoListView lainnya di onAppearing() dan OnReloadButtonClicked(). Hah? Bagaimana penambahan referensi variabel di event handler membuat variabel itu tidak valid dalam metode yang sama sekali berbeda? Oke, ada yang mencurigakan dengan variabel sebelumnya (masih belum tahu apa...), tapi berhasil. Sekarang tidak ada lagi, yang tidak masuk akal bagi saya. Selanjutnya, jika saya mengomentari baris yang menyinggung di event handler DoneSwitchToggled, dan memasukkan definisi dummy untuk i, seperti:
TodoItem i = null;
// TodoItem i = TodoListView.SelectedItem;
semuanya seperti sebelumnya, VS masih menggarisbawahi tampilan TodoListView lainnya, tetapi sekarang program dibangun dan berjalan dengan baik kembali.
Adakah yang bisa menjelaskan efek ini, dan menunjukkan seberapa benar kode saya? Saya pikir tujuannya jelas: DoneSwitchToggled seharusnya menulis kembali nilai saklar ke dalam database (dan melakukan beberapa pemrosesan lain yang tidak ditampilkan dalam sampel saya), dan meskipun objek "pengirim" disetel dengan benar untuk mereferensikan tombol saya, saya tidak menemukan cara untuk mengakses pengikatan data yang mendasarinya, karena sayangnya ToggledEventArgs tampaknya hanya meneruskan posisi sakelar "benar" atau "salah", tetapi - tidak seperti pengendali peristiwa OnListItemSelected - tidak meneruskan referensi apa pun ke baris terikat melalui argumen kedua. Jadi ide saya adalah menggunakan ListView.SelectedItem untuk tujuan ini.