如何在页面出现时填充 C# MAUI 选择器?

huangapple go评论128阅读模式
英文:

How to populate C# MAUI picker when page appears?

问题

你好,以下是你要翻译的内容:

ClassEditPage.xaml

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  4. x:Class="Studio_Sign_In_202307.Pages.ClassEditPage"
  5. Title="ClassEditPage">
  6. <StackLayout Padding="20">
  7. <!--
  8. <Label Text="Instructor:" />
  9. <Entry Text="{Binding cInstructor}" />
  10. -->
  11. <!-- Instructor Picker -->
  12. <Label Text="Instructor:" />
  13. <Picker x:Name="Instructor_Picker"
  14. Title="Select an Instructor"
  15. ItemsSource="{Binding InstructorsList}"
  16. SelectedItem="{Binding SelectedInstructor}"
  17. SelectedIndexChanged="Instructor_Picker_SelectedIndexChanged">
  18. <Picker.ItemDisplayBinding>
  19. <!-- Display the instructor's full name in the picker -->
  20. <Binding Path="iFullName" />
  21. </Picker.ItemDisplayBinding>
  22. </Picker>
  23. <Button Text="Submit" Clicked="OnSubmitClicked" />
  24. <Button Text="Delete" Clicked="OnDeleteClicked" IsVisible="{Binding cID, Converter={StaticResource HasValueConverter}}" />
  25. <Button Text="Cancel" Clicked="OnCancelClicked" />
  26. </StackLayout>
  27. </ContentPage>

ClassEditPage.xaml.cs

  1. using Studio_Sign_In_202307.Data;
  2. using Studio_Sign_In_202307.Models;
  3. using System.Collections.ObjectModel;
  4. using System.Diagnostics;
  5. namespace Studio_Sign_In_202307.Pages;
  6. public partial class ClassEditPage : ContentPage
  7. {
  8. private readonly Class selectedClass;
  9. private readonly bool isNewClass;
  10. // Property to hold the collection of instructors
  11. public ObservableCollection<Instructor> InstructorsList { get; set; }
  12. // Property to hold the selected instructor
  13. public Instructor SelectedInstructor { get; set; }
  14. public ClassEditPage(Class selectedClass)
  15. {
  16. InitializeComponent();
  17. // Determine if this is an existing class or a new class
  18. isNewClass = selectedClass == null;
  19. this.selectedClass = selectedClass ?? new Class();
  20. BindingContext = this.selectedClass;
  21. // Create Connection String
  22. string connectionString = DatabaseHelper.BuildConnectionString();
  23. // Set the InstructorsList with the data from the database
  24. InstructorsList = DatabaseHelper.GetInstructorsAll(connectionString);
  25. // Debug instructor list <-- This Displays My Instructors
  26. foreach (Instructor instructor in InstructorsList)
  27. {
  28. Debug.WriteLine($"Instructor ID: {instructor.iID}");
  29. Debug.WriteLine($"Full Name: {instructor.iFullName}");
  30. Debug.WriteLine($"Email: {instructor.iEmail}");
  31. Debug.WriteLine("------------------------");
  32. }
  33. // Set the selected instructor for the class (if it has one)
  34. if (selectedClass.iID_Link != 0)
  35. {
  36. SelectedInstructor = InstructorsList.FirstOrDefault(i => i.iID == selectedClass.iID_Link);
  37. Instructor_Picker.SelectedIndex = InstructorsList.IndexOf(SelectedInstructor);
  38. }
  39. }
  40. private void Instructor_Picker_SelectedIndexChanged(object sender, EventArgs e)
  41. {
  42. if (Instructor_Picker.SelectedItem is Instructor selectedInstructor)
  43. {
  44. SelectedInstructor = selectedInstructor;
  45. }
  46. }
  47. private void OnSubmitClicked(object sender, EventArgs e)
  48. {
  49. Debug.WriteLine("SUBMIT");
  50. // Submit Logic Here
  51. Navigation.PopModalAsync();
  52. }
  53. private void OnDeleteClicked(object sender, EventArgs e)
  54. {
  55. Debug.WriteLine("DELETE");
  56. // Delete Logic Here
  57. Navigation.PopModalAsync();
  58. }
  59. private void OnCancelClicked(object sender, EventArgs e)
  60. {
  61. Navigation.PopModalAsync();
  62. }
  63. }

Debug Output

  1. Instructor ID: 44
  2. Full Name: Lori
  3. Email: LoriTest@gmail.com
  4. ------------------------
  5. Instructor ID: 38
  6. Full Name: Bret
  7. Email: BretTest@gmail.com
  8. ------------------------
  9. Instructor ID: 56
  10. Full Name: Jessica
  11. Email: JessTest@gmail.com
  12. ------------------------

希望这对你有帮助!

英文:

I'm trying to figure out how to load a picker when a page appears.

ClassEditPage has Instructor_Picker (shown below). I know the code to populate it works because it gives Debug output (shown below), however, my picker is never populated. There are no errors, just a blank picker.

Can you help me figure out how to populate the Instructor_Picker when my ClassEditPage appears?


ClassEditPage.xaml

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
  2. &lt;ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
  3. xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
  4. x:Class=&quot;Studio_Sign_In_202307.Pages.ClassEditPage&quot;
  5. Title=&quot;ClassEditPage&quot;&gt;
  6. &lt;StackLayout Padding=&quot;20&quot;&gt;
  7. &lt;!--&lt;Label Text=&quot;Instructor:&quot; /&gt;
  8. &lt;Entry Text=&quot;{Binding cInstructor}&quot; /&gt;--&gt;
  9. &lt;!-- Instructor Picker --&gt;
  10. &lt;Label Text=&quot;Instructor:&quot; /&gt;
  11. &lt;Picker x:Name=&quot;Instructor_Picker&quot;
  12. Title=&quot;Select an Instructor&quot;
  13. ItemsSource=&quot;{Binding InstructorsList}&quot;
  14. SelectedItem=&quot;{Binding SelectedInstructor}&quot;
  15. SelectedIndexChanged=&quot;Instructor_Picker_SelectedIndexChanged&quot;&gt;
  16. &lt;Picker.ItemDisplayBinding&gt;
  17. &lt;!-- Display the instructor&#39;s full name in the picker --&gt;
  18. &lt;Binding Path=&quot;iFullName&quot; /&gt;
  19. &lt;/Picker.ItemDisplayBinding&gt;
  20. &lt;/Picker&gt;
  21. &lt;Button Text=&quot;Submit&quot; Clicked=&quot;OnSubmitClicked&quot; /&gt;
  22. &lt;Button Text=&quot;Delete&quot; Clicked=&quot;OnDeleteClicked&quot; IsVisible=&quot;{Binding cID, Converter={StaticResource HasValueConverter}}&quot; /&gt;
  23. &lt;Button Text=&quot;Cancel&quot; Clicked=&quot;OnCancelClicked&quot; /&gt;
  24. &lt;/StackLayout&gt;
  25. &lt;/ContentPage&gt;

ClassEditPage.xaml.cs

  1. using Studio_Sign_In_202307.Data;
  2. using Studio_Sign_In_202307.Models;
  3. using System.Collections.ObjectModel;
  4. using System.Diagnostics;
  5. namespace Studio_Sign_In_202307.Pages;
  6. public partial class ClassEditPage : ContentPage
  7. {
  8. private readonly Class selectedClass;
  9. private readonly bool isNewClass;
  10. // Property to hold the collection of instructors
  11. public ObservableCollection&lt;Instructor&gt; InstructorsList { get; set; }
  12. // Property to hold the selected instructor
  13. public Instructor SelectedInstructor { get; set; }
  14. public ClassEditPage(Class selectedClass)
  15. {
  16. InitializeComponent();
  17. // Determine if this is an existing class or a new class
  18. isNewClass = selectedClass == null;
  19. this.selectedClass = selectedClass ?? new Class();
  20. BindingContext = this.selectedClass;
  21. // Create Connection String
  22. string connectionString = DatabaseHelper.BuildConnectionString();
  23. // Set the InstructorsList with the data from the database
  24. InstructorsList = DatabaseHelper.GetInstructorsAll(connectionString);
  25. // Debug instructor list &lt;-- This Displays My Instructors
  26. foreach (Instructor instructor in InstructorsList)
  27. {
  28. Debug.WriteLine($&quot;Instructor ID: {instructor.iID}&quot;);
  29. Debug.WriteLine($&quot;Full Name: {instructor.iFullName}&quot;);
  30. Debug.WriteLine($&quot;Email: {instructor.iEmail}&quot;);
  31. Debug.WriteLine(&quot;------------------------&quot;);
  32. }
  33. // Set the selected instructor for the class (if it has one)
  34. if (selectedClass.iID_Link != 0)
  35. {
  36. SelectedInstructor = InstructorsList.FirstOrDefault(i =&gt; i.iID == selectedClass.iID_Link);
  37. Instructor_Picker.SelectedIndex = InstructorsList.IndexOf(SelectedInstructor);
  38. }
  39. }
  40. private void Instructor_Picker_SelectedIndexChanged(object sender, EventArgs e)
  41. {
  42. if (Instructor_Picker.SelectedItem is Instructor selectedInstructor)
  43. {
  44. SelectedInstructor = selectedInstructor;
  45. }
  46. }
  47. private void OnSubmitClicked(object sender, EventArgs e)
  48. {
  49. Debug.WriteLine(&quot;SUBMIT&quot;);
  50. // Submit Logic Here
  51. Navigation.PopModalAsync();
  52. }
  53. private void OnDeleteClicked(object sender, EventArgs e)
  54. {
  55. Debug.WriteLine(&quot;DELETE&quot;);
  56. // Delete Logic Here
  57. Navigation.PopModalAsync();
  58. }
  59. private void OnCancelClicked(object sender, EventArgs e)
  60. {
  61. Navigation.PopModalAsync();
  62. }
  63. }

Dubug Output

  1. Instructor ID: 44
  2. Full Name: Lori
  3. Email: LoriTest@gmail.com
  4. ------------------------
  5. Instructor ID: 38
  6. Full Name: Bret
  7. Email: BretTest@gmail.com
  8. ------------------------
  9. Instructor ID: 56
  10. Full Name: Jessica
  11. Email: JessTest@gmail.com
  12. ------------------------

Thanks for your help!

答案1

得分: 1

以下是您要翻译的内容:

"Ok, here we go. Firstly we need to learn about MVVM. It makes your life so much easier and it separates your code and makes it more structured and testable and maintainable. So we're going to separate your code into a ViewModel where all business logic is and let the view take care of all that it is best for, the controls and views. I have slimmed down your code but it all works as you want, even the delete button. You should consider making the Buttons use commands and handle logic in the ViewModel.

The ViewModel looks like this:

  1. public partial class ClassEditViewModel : ObservableObject
  2. {
  3. public ClassEditViewModel()
  4. {
  5. // Set the InstructorsList with the data from the database
  6. InstructorsList = GetInstructor();
  7. }
  8. // Property to hold the collection of instructors
  9. [ObservableProperty]
  10. private ObservableCollection&lt;Instructor&gt; _instructorsList;
  11. }

Your view looks like this now:

  1. &lt;ContentPage.Resources&gt;
  2. &lt;ResourceDictionary&gt;
  3. &lt;converters:NullToBoolConverter x:Key=&quot;NullToBoolConverter&quot; /&gt;
  4. &lt;/ResourceDictionary&gt;
  5. &lt;/ContentPage.Resources&gt;
  6. &lt;StackLayout Padding = &quot;20&quot; &gt;
  7. &lt;Label Text=&quot;Instructor:&quot; /&gt;
  8. &lt;Picker
  9. x:Name=&quot;Instructor_Picker&quot;
  10. Title=&quot;Select an Instructor&quot;
  11. ItemsSource=&quot;{Binding InstructorsList}&quot;&gt;
  12. &lt;Picker.ItemDisplayBinding&gt;
  13. &lt;!-- Display the instructor&#39;s full name in the picker --&gt;
  14. &lt;Binding Path = &quot;FullName&quot; /&gt;
  15. &lt;/Picker.ItemDisplayBinding &gt;
  16. &lt;/Picker &gt;
  17. &lt;Button Clicked=&quot;OnSubmitClicked&quot; Text=&quot;Submit&quot; /&gt;
  18. &lt;Button
  19. Clicked = &quot;OnDeleteClicked&quot;
  20. IsEnabled=&quot;{Binding Source={x:Reference Instructor_Picker}, Path=SelectedItem, Converter={StaticResource NullToBoolConverter}}&quot;
  21. Text=&quot;Delete&quot; /&gt;
  22. &lt;Button Clicked = &quot;OnCancelClicked&quot; Text=&quot;Cancel&quot; /&gt;
  23. &lt;/StackLayout&gt;

And your View Code Behind is this now. Much more maintainable IMHO.

  1. public TestPage()
  2. {
  3. InitializeComponent();
  4. BindingContext = new ClassEditViewModel();
  5. }
  6. private void OnSubmitClicked(object sender, EventArgs e)
  7. {
  8. }
  9. private void OnCancelClicked(object sender, EventArgs e)
  10. {
  11. }
  12. private void OnDeleteClicked(object sender, EventArgs e)
  13. {
  14. Toast.Make(&quot;Delete user&quot;).Show();
  15. }

I made a lite converter for you if you want it:

  1. public class NullToBoolConverter : IValueConverter
  2. {
  3. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  4. {
  5. return value != null;
  6. }
  7. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  8. {
  9. throw new NotImplementedException();
  10. }
  11. }
英文:

Ok, here we go. Firstly we need to learn about MVVM. It makes your life so much easier and it separate your code and makes it more structured and testable and maintainable. So we going to separate your code into a ViewModel where all business logic is and let the view take care of all that it is best for, the controls and views. I have slimed down your code but it all work as you want, even the delete button. You should consider to make the Buttons use commands and handle logic in the ViewModel.

The ViewModel looks like this:

  1. public partial class ClassEditViewModel : ObservableObject
  2. {
  3. public ClassEditViewModel()
  4. {
  5. // Set the InstructorsList with the data from the database
  6. InstructorsList = GetInstructor();
  7. }
  8. // Property to hold the collection of instructors
  9. [ObservableProperty]
  10. private ObservableCollection&lt;Instructor&gt; _instructorsList;
  11. }

Your view looks like this now:

  1. &lt;ContentPage.Resources&gt;
  2. &lt;ResourceDictionary&gt;
  3. &lt;converters:NullToBoolConverter x:Key=&quot;NullToBoolConverter&quot; /&gt;
  4. &lt;/ResourceDictionary&gt;
  5. &lt;/ContentPage.Resources&gt;
  6. &lt;StackLayout Padding = &quot;20&quot; &gt;
  7. &lt;Label Text=&quot;Instructor:&quot; /&gt;
  8. &lt;Picker
  9. x:Name=&quot;Instructor_Picker&quot;
  10. Title=&quot;Select an Instructor&quot;
  11. ItemsSource=&quot;{Binding InstructorsList}&quot;&gt;
  12. &lt;Picker.ItemDisplayBinding&gt;
  13. &lt;!-- Display the instructor&#39;s full name in the picker --&gt;
  14. &lt;Binding Path = &quot;FullName&quot; /&gt;
  15. &lt;/Picker.ItemDisplayBinding &gt;
  16. &lt;/Picker &gt;
  17. &lt;Button Clicked=&quot;OnSubmitClicked&quot; Text=&quot;Submit&quot; /&gt;
  18. &lt;Button
  19. Clicked = &quot;OnDeleteClicked&quot;
  20. IsEnabled=&quot;{Binding Source={x:Reference Instructor_Picker}, Path=SelectedItem, Converter={StaticResource NullToBoolConverter}}&quot;
  21. Text=&quot;Delete&quot; /&gt;
  22. &lt;Button Clicked = &quot;OnCancelClicked&quot; Text=&quot;Cancel&quot; /&gt;
  23. &lt;/StackLayout&gt;

And your View Code Behind is this now. Much more maintainable IMHO.

  1. public TestPage()
  2. {
  3. InitializeComponent();
  4. BindingContext = new ClassEditViewModel();
  5. }
  6. private void OnSubmitClicked(object sender, EventArgs e)
  7. {
  8. }
  9. private void OnCancelClicked(object sender, EventArgs e)
  10. {
  11. }
  12. private void OnDeleteClicked(object sender, EventArgs e)
  13. {
  14. Toast.Make(&quot;Delete user&quot;).Show();
  15. }

I made a lite converter for you if you want it:

  1. public class NullToBoolConverter : IValueConverter
  2. {
  3. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  4. {
  5. return value != null;
  6. }
  7. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  8. {
  9. throw new NotImplementedException();
  10. }
  11. }

答案2

得分: 0

我需要直接将'InstructorsList'和'SelectedInstructor'属性添加到Class.cs数据模型中,如下所示:

  1. public ObservableCollection<Instructor> InstructorsList { get; set; }
  2. public Instructor SelectedInstructor { get; set; }

我在ClassEditPage.xaml.cs中删除了这两个本地初始化:

  1. public ObservableCollection<Instructor> InstructorsList { get; set; }
  2. public Instructor SelectedInstructor { get; set; }

然后,在ClassEditPage.xaml.cs构造函数中填充它们,如下所示:

  1. this.selectedClass.InstructorsList = new ObservableCollection<Instructor>(DatabaseHelper.GetInstructorsAll(connectionString));
  2. ...
  3. this.selectedClass.SelectedInstructor = this.selectedClass.InstructorsList.FirstOrDefault(i => i.iID == selectedClass.iID_Link);
英文:

I needed to add the 'InstructorsList' and 'SelectedInstructor' properties directly to the Class.cs data model like this:

  1. public ObservableCollection&lt;Instructor&gt; InstructorsList { get; set; }
  2. public Instructor SelectedInstructor { get; set; }

I eliminated these two local initializations in ClassEditPage.xaml.cs:

  1. public ObservableCollection&lt;Instructor&gt; InstructorsList { get; set; }
  2. public Instructor SelectedInstructor { get; set; }

And then I populated them in the ClassEditPage.xaml.cs constructor, like this:

  1. this.selectedClass.InstructorsList = new ObservableCollection&lt;Instructor&gt;(DatabaseHelper.GetInstructorsAll(connectionString));
  2. ...
  3. this.selectedClass.SelectedInstructor = this.selectedClass.InstructorsList.FirstOrDefault(i =&gt; i.iID == selectedClass.iID_Link);

huangapple
  • 本文由 发表于 2023年8月5日 00:02:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76837536.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定