ฉันมีปัญหาแปลก ๆ กับขอบเขตตัวแปร Listview ชื่อ "TodoListView" ถูกกำหนดผ่าน xaml และเป็น ItemSource ที่เติมจากฐานข้อมูล SQListe ได้ผล ภายใน ListView ฉันมี ViewCell เพื่อแสดงข้อมูลตามแถว
<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);
}
}
}
}
ความแปลกประหลาดมีสองขั้นตอน ก่อนที่ฉันจะแทรกตัวจัดการเหตุการณ์ DoneSwitchToggled ทุกเหตุการณ์ของ TodoListView.ItemsSource ได้รับการขีดเส้นใต้สีแดงภายใต้ TodoListView และคำใบ้ว่า "ชื่อ TodoListView ไม่มีอยู่ในบริบทปัจจุบัน" โอเค ฉันคิดว่า VS ไม่ฉลาดพอที่จะค้นหาคำจำกัดความในไฟล์ xaml เพราะถึงแม้จะมีคำเตือน โปรแกรมก็คอมไพล์และทำงานได้ดี TodoListView ได้รับการเตรียมใช้งานและแสดงแถวของฐานข้อมูลที่เกี่ยวข้องอย่างถูกต้อง ดังนั้นจึงมีอยู่อย่างชัดเจนในขณะรันไทม์
สิ่งต่าง ๆ เกิดขึ้นอย่างรวดเร็วเมื่อฉันเพิ่มตัวจัดการเหตุการณ์ DoneSwitchToggled ให้กับทั้ง XAML และโค้ดด้านหลัง ทันใดนั้นโปรแกรมจะไม่คอมไพล์อีกต่อไป แต่ประกันตัวด้วยข้อผิดพลาด CS0103 "ชื่อ "TodoListView" ไม่มีอยู่ในบริบทปัจจุบัน" ข้อผิดพลาดปรากฏขึ้นสามครั้ง โดยหมายเลขบรรทัดชี้ไปที่เหตุการณ์อื่นๆ ของ TodoListView ใน onAppearing() และ OnReloadButtonClicked() ฮะ? การเพิ่มการอ้างอิงตัวแปรในตัวจัดการเหตุการณ์ทำให้ตัวแปรนั้นไม่ถูกต้องในวิธีที่ต่างกันโดยสิ้นเชิงได้อย่างไร ตกลง ก่อนหน้านี้มีบางสิ่งที่คาวกับตัวแปร (ยังไม่รู้ว่าอะไร ... ) แต่มันก็ได้ผล ตอนนี้มันไม่มีอีกแล้ว ซึ่งมันไม่สมเหตุสมผลสำหรับฉัน นอกจากนี้ หากฉันใส่ความคิดเห็นเกี่ยวกับบรรทัดที่ละเมิดในตัวจัดการเหตุการณ์ DoneSwitchToggled และใส่คำจำกัดความจำลองสำหรับ i ดังนี้:
TodoItem i = null;
// TodoItem i = TodoListView.SelectedItem;
ทุกอย่างเหมือนเดิม VS ยังคงเน้นย้ำลักษณะที่ปรากฏอื่นๆ ของ TodoListView แต่ตอนนี้โปรแกรมสร้างและทำงานได้อีกครั้ง
ใครก็ตามที่สามารถอธิบายผลกระทบนี้ และแสดงให้ฉันเห็นว่ารหัสของฉันถูกต้องอย่างไร ฉันคิดว่าวัตถุประสงค์นั้นชัดเจน: DoneSwitchToggled ควรจะเขียนกลับค่าสวิตช์ลงในฐานข้อมูล (และทำการประมวลผลอื่น ๆ ที่ไม่แสดงในตัวอย่างที่แยกออกมาของฉัน) และแม้ว่าวัตถุ "ผู้ส่ง" จะได้รับการตั้งค่าอย่างถูกต้องเพื่ออ้างอิงปุ่มของฉัน แต่ฉัน ไม่พบวิธีเข้าถึงการเชื่อมโยงข้อมูลพื้นฐาน เนื่องจาก ToggledEventArgs ดูเหมือนจะผ่านตำแหน่งสวิตช์ "จริง" หรือ "เท็จ" เท่านั้น แต่ - ไม่เหมือนกับตัวจัดการเหตุการณ์ OnListItemSelected - ไม่ผ่านการอ้างอิงใด ๆ ไปยังแถวที่ถูกผูกไว้ผ่านอาร์กิวเมนต์ที่สอง ดังนั้นความคิดของฉันคือใช้ ListView.SelectedItem เพื่อจุดประสงค์นี้