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

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

How to populate C# MAUI picker when page appears?

问题

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

ClassEditPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Studio_Sign_In_202307.Pages.ClassEditPage"
             Title="ClassEditPage">

    <StackLayout Padding="20">

        <!--
        <Label Text="Instructor:" />
        <Entry Text="{Binding cInstructor}" />
        -->

        <!-- Instructor Picker -->
        <Label Text="Instructor:" />
        <Picker x:Name="Instructor_Picker"
                Title="Select an Instructor"
                ItemsSource="{Binding InstructorsList}" 
                SelectedItem="{Binding SelectedInstructor}" 
                SelectedIndexChanged="Instructor_Picker_SelectedIndexChanged">
            <Picker.ItemDisplayBinding>
                <!-- Display the instructor's full name in the picker -->
                <Binding Path="iFullName" />
            </Picker.ItemDisplayBinding>
        </Picker>

        <Button Text="Submit" Clicked="OnSubmitClicked" />
        <Button Text="Delete" Clicked="OnDeleteClicked" IsVisible="{Binding cID, Converter={StaticResource HasValueConverter}}" />
        <Button Text="Cancel" Clicked="OnCancelClicked" />
        
    </StackLayout>
</ContentPage>

ClassEditPage.xaml.cs

using Studio_Sign_In_202307.Data;
using Studio_Sign_In_202307.Models;
using System.Collections.ObjectModel;
using System.Diagnostics;

namespace Studio_Sign_In_202307.Pages;

public partial class ClassEditPage : ContentPage
{
    private readonly Class selectedClass;
    private readonly bool isNewClass;

    // Property to hold the collection of instructors
    public ObservableCollection<Instructor> InstructorsList { get; set; }

    // Property to hold the selected instructor
    public Instructor SelectedInstructor { get; set; }

    public ClassEditPage(Class selectedClass)
    {
        InitializeComponent();

        // Determine if this is an existing class or a new class
        isNewClass = selectedClass == null;
        this.selectedClass = selectedClass ?? new Class();

        BindingContext = this.selectedClass;

        // Create Connection String
        string connectionString = DatabaseHelper.BuildConnectionString();

        // Set the InstructorsList with the data from the database
        InstructorsList = DatabaseHelper.GetInstructorsAll(connectionString);

        // Debug instructor list <-- This Displays My Instructors
        foreach (Instructor instructor in InstructorsList)
        {
            Debug.WriteLine($"Instructor ID: {instructor.iID}");
            Debug.WriteLine($"Full Name: {instructor.iFullName}");
            Debug.WriteLine($"Email: {instructor.iEmail}");
            Debug.WriteLine("------------------------");
        }

        // Set the selected instructor for the class (if it has one)
        if (selectedClass.iID_Link != 0)
        {
            SelectedInstructor = InstructorsList.FirstOrDefault(i => i.iID == selectedClass.iID_Link);
            Instructor_Picker.SelectedIndex = InstructorsList.IndexOf(SelectedInstructor);
        }
    }

    private void Instructor_Picker_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (Instructor_Picker.SelectedItem is Instructor selectedInstructor)
        {
            SelectedInstructor = selectedInstructor;
        }
    }

    private void OnSubmitClicked(object sender, EventArgs e)
    {
        Debug.WriteLine("SUBMIT");
        // Submit Logic Here
        Navigation.PopModalAsync();
    }

    private void OnDeleteClicked(object sender, EventArgs e)
    {
        Debug.WriteLine("DELETE");
        // Delete Logic Here
        Navigation.PopModalAsync();
    }

    private void OnCancelClicked(object sender, EventArgs e)
    {
        Navigation.PopModalAsync();
    }
}

Debug Output

Instructor ID: 44
Full Name: Lori
Email: LoriTest@gmail.com
------------------------
Instructor ID: 38
Full Name: Bret
Email: BretTest@gmail.com
------------------------
Instructor ID: 56
Full Name: Jessica
Email: JessTest@gmail.com
------------------------

希望这对你有帮助!

英文:

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

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
x:Class=&quot;Studio_Sign_In_202307.Pages.ClassEditPage&quot;
Title=&quot;ClassEditPage&quot;&gt;
&lt;StackLayout Padding=&quot;20&quot;&gt;
&lt;!--&lt;Label Text=&quot;Instructor:&quot; /&gt;
&lt;Entry Text=&quot;{Binding cInstructor}&quot; /&gt;--&gt;
&lt;!-- Instructor Picker --&gt;
&lt;Label Text=&quot;Instructor:&quot; /&gt;
&lt;Picker x:Name=&quot;Instructor_Picker&quot;
Title=&quot;Select an Instructor&quot;
ItemsSource=&quot;{Binding InstructorsList}&quot; 
SelectedItem=&quot;{Binding SelectedInstructor}&quot; 
SelectedIndexChanged=&quot;Instructor_Picker_SelectedIndexChanged&quot;&gt;
&lt;Picker.ItemDisplayBinding&gt;
&lt;!-- Display the instructor&#39;s full name in the picker --&gt;
&lt;Binding Path=&quot;iFullName&quot; /&gt;
&lt;/Picker.ItemDisplayBinding&gt;
&lt;/Picker&gt;
&lt;Button Text=&quot;Submit&quot; Clicked=&quot;OnSubmitClicked&quot; /&gt;
&lt;Button Text=&quot;Delete&quot; Clicked=&quot;OnDeleteClicked&quot; IsVisible=&quot;{Binding cID, Converter={StaticResource HasValueConverter}}&quot; /&gt;
&lt;Button Text=&quot;Cancel&quot; Clicked=&quot;OnCancelClicked&quot; /&gt;
&lt;/StackLayout&gt;
&lt;/ContentPage&gt;

ClassEditPage.xaml.cs

using Studio_Sign_In_202307.Data;
using Studio_Sign_In_202307.Models;
using System.Collections.ObjectModel;
using System.Diagnostics;
namespace Studio_Sign_In_202307.Pages;
public partial class ClassEditPage : ContentPage
{
private readonly Class selectedClass;
private readonly bool isNewClass;
// Property to hold the collection of instructors
public ObservableCollection&lt;Instructor&gt; InstructorsList { get; set; }
// Property to hold the selected instructor
public Instructor SelectedInstructor { get; set; }
public ClassEditPage(Class selectedClass)
{
InitializeComponent();
// Determine if this is an existing class or a new class
isNewClass = selectedClass == null;
this.selectedClass = selectedClass ?? new Class();
BindingContext = this.selectedClass;
// Create Connection String
string connectionString = DatabaseHelper.BuildConnectionString();
// Set the InstructorsList with the data from the database
InstructorsList = DatabaseHelper.GetInstructorsAll(connectionString);
// Debug instructor list &lt;-- This Displays My Instructors
foreach (Instructor instructor in InstructorsList)
{
Debug.WriteLine($&quot;Instructor ID: {instructor.iID}&quot;);
Debug.WriteLine($&quot;Full Name: {instructor.iFullName}&quot;);
Debug.WriteLine($&quot;Email: {instructor.iEmail}&quot;);
Debug.WriteLine(&quot;------------------------&quot;);
}
// Set the selected instructor for the class (if it has one)
if (selectedClass.iID_Link != 0)
{
SelectedInstructor = InstructorsList.FirstOrDefault(i =&gt; i.iID == selectedClass.iID_Link);
Instructor_Picker.SelectedIndex = InstructorsList.IndexOf(SelectedInstructor);
}
}
private void Instructor_Picker_SelectedIndexChanged(object sender, EventArgs e)
{
if (Instructor_Picker.SelectedItem is Instructor selectedInstructor)
{
SelectedInstructor = selectedInstructor;
}
}
private void OnSubmitClicked(object sender, EventArgs e)
{
Debug.WriteLine(&quot;SUBMIT&quot;);
// Submit Logic Here
Navigation.PopModalAsync();
}
private void OnDeleteClicked(object sender, EventArgs e)
{
Debug.WriteLine(&quot;DELETE&quot;);
// Delete Logic Here
Navigation.PopModalAsync();
}
private void OnCancelClicked(object sender, EventArgs e)
{
Navigation.PopModalAsync();
}
}

Dubug Output

Instructor ID: 44
Full Name: Lori
Email: LoriTest@gmail.com
------------------------
Instructor ID: 38
Full Name: Bret
Email: BretTest@gmail.com
------------------------
Instructor ID: 56
Full Name: Jessica
Email: JessTest@gmail.com
------------------------

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:

public partial class ClassEditViewModel : ObservableObject
{
    public ClassEditViewModel()
    {
        // Set the InstructorsList with the data from the database
        InstructorsList = GetInstructor();
    }

    // Property to hold the collection of instructors
    [ObservableProperty]
    private ObservableCollection&lt;Instructor&gt; _instructorsList;
}

Your view looks like this now:

&lt;ContentPage.Resources&gt;
&lt;ResourceDictionary&gt;
&lt;converters:NullToBoolConverter x:Key=&quot;NullToBoolConverter&quot; /&gt;
&lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;
&lt;StackLayout Padding = &quot;20&quot; &gt;
&lt;Label Text=&quot;Instructor:&quot; /&gt;
&lt;Picker
x:Name=&quot;Instructor_Picker&quot;
Title=&quot;Select an Instructor&quot;
ItemsSource=&quot;{Binding InstructorsList}&quot;&gt;
&lt;Picker.ItemDisplayBinding&gt;
&lt;!--  Display the instructor&#39;s full name in the picker  --&gt;
&lt;Binding Path = &quot;FullName&quot; /&gt;
&lt;/Picker.ItemDisplayBinding &gt;
&lt;/Picker &gt;
&lt;Button Clicked=&quot;OnSubmitClicked&quot; Text=&quot;Submit&quot; /&gt;
&lt;Button
Clicked = &quot;OnDeleteClicked&quot;
IsEnabled=&quot;{Binding Source={x:Reference Instructor_Picker}, Path=SelectedItem, Converter={StaticResource NullToBoolConverter}}&quot;
Text=&quot;Delete&quot; /&gt;
&lt;Button Clicked = &quot;OnCancelClicked&quot; Text=&quot;Cancel&quot; /&gt;
&lt;/StackLayout&gt;

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

public TestPage()
{
    InitializeComponent();
    BindingContext = new ClassEditViewModel();
}

private void OnSubmitClicked(object sender, EventArgs e)
{

}

private void OnCancelClicked(object sender, EventArgs e)
{

}

private void OnDeleteClicked(object sender, EventArgs e)
{
    Toast.Make(&quot;Delete user&quot;).Show();
}

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

public class NullToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value != null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
英文:

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:

public partial class ClassEditViewModel : ObservableObject
{
    public ClassEditViewModel()
    {
        // Set the InstructorsList with the data from the database
        InstructorsList = GetInstructor();
    }

    // Property to hold the collection of instructors
    [ObservableProperty]
    private ObservableCollection&lt;Instructor&gt; _instructorsList;
}

Your view looks like this now:

&lt;ContentPage.Resources&gt;
&lt;ResourceDictionary&gt;
&lt;converters:NullToBoolConverter x:Key=&quot;NullToBoolConverter&quot; /&gt;
&lt;/ResourceDictionary&gt;
&lt;/ContentPage.Resources&gt;
&lt;StackLayout Padding = &quot;20&quot; &gt;
&lt;Label Text=&quot;Instructor:&quot; /&gt;
&lt;Picker
x:Name=&quot;Instructor_Picker&quot;
Title=&quot;Select an Instructor&quot;
ItemsSource=&quot;{Binding InstructorsList}&quot;&gt;
&lt;Picker.ItemDisplayBinding&gt;
&lt;!--  Display the instructor&#39;s full name in the picker  --&gt;
&lt;Binding Path = &quot;FullName&quot; /&gt;
&lt;/Picker.ItemDisplayBinding &gt;
&lt;/Picker &gt;
&lt;Button Clicked=&quot;OnSubmitClicked&quot; Text=&quot;Submit&quot; /&gt;
&lt;Button
Clicked = &quot;OnDeleteClicked&quot;
IsEnabled=&quot;{Binding Source={x:Reference Instructor_Picker}, Path=SelectedItem, Converter={StaticResource NullToBoolConverter}}&quot;
Text=&quot;Delete&quot; /&gt;
&lt;Button Clicked = &quot;OnCancelClicked&quot; Text=&quot;Cancel&quot; /&gt;
&lt;/StackLayout&gt;

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

public TestPage()
{
    InitializeComponent();
    BindingContext = new ClassEditViewModel();


}

private void OnSubmitClicked(object sender, EventArgs e)
{

}

private void OnCancelClicked(object sender, EventArgs e)
{

}

private void OnDeleteClicked(object sender, EventArgs e)
{
    Toast.Make(&quot;Delete user&quot;).Show();
}

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

public class NullToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value != null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

答案2

得分: 0

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

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

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

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

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

this.selectedClass.InstructorsList = new ObservableCollection<Instructor>(DatabaseHelper.GetInstructorsAll(connectionString));

...

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:

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

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

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

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

this.selectedClass.InstructorsList = new ObservableCollection&lt;Instructor&gt;(DatabaseHelper.GetInstructorsAll(connectionString));
...
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:

确定