XAML 已调用PropertyChanged,但UI未在MAUI中更新

zf2sa74q  于 2022-12-16  发布在  其他
关注(0)|答案(2)|浏览(133)

嗨,我正在开发一个简单的测试应用程序在MAUI的windows。
问题是调用PropertyChanged时视图页面中的标签不会更改。
我发现当我更改[PortErrorMsg]属性时,我可以看到PropertyChanged函数被调用,但是
未调用[PortErrorMsg]属性中的“get”。
(Debug.WriteLine(“用于检查get是否正常工作的消息”);〈--这不叫。)
下面是我的代码
XAML:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:NxJig.ViewModels"
             x:DataType="vm:JigViewModel"
             x:Class="NxJig.Views.JigPage"
             Title="JigPage">
    
    <ContentPage.BindingContext>
        <vm:JigViewModel/>
    </ContentPage.BindingContext>

    <VerticalStackLayout>
        <HorizontalStackLayout Margin="30">
            <Picker Title="Select Port" x:Name="picker1" SelectedIndexChanged="picker1_SelectedIndexChanged" FontSize="Large">
                <Picker.Items>
                    <x:String>COM1</x:String>
                    <x:String>COM2</x:String>
                    <x:String>COM3</x:String>
                    <x:String>COM4</x:String>
                    <x:String>COM5</x:String>
                    <x:String>COM6</x:String>
                    <x:String>COM7</x:String>
                    <x:String>COM8</x:String>
                    <x:String>COM9</x:String>
                    <x:String>COM10</x:String>
                    <x:String>COM11</x:String>
                    <x:String>COM12</x:String>
                    <x:String>COM13</x:String>
                    <x:String>COM14</x:String>
                    <x:String>COM15</x:String>
                    <x:String>COM16</x:String>
                    <x:String>COM17</x:String>
                    <x:String>COM18</x:String>
                    <x:String>COM19</x:String>
                    <x:String>COM20</x:String>
                </Picker.Items>
            </Picker>
        </HorizontalStackLayout>
            <Label Text="{Binding PortErrorMsg, Mode=TwoWay}" IsEnabled="True" FontSize="Large"/>
    </VerticalStackLayout>
</ContentPage>

Xaml隐藏代码:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void picker1_SelectedIndexChanged(object sender, EventArgs e)
    {
        ViewModel vm = new ViewModel();
        vm.SerialPortName = picker1.SelectedItem as string;
    }
}

视图模型:

namespace NxJig.ViewModels
{
    public class JigViewModel : INotifyPropertyChanged
    {
        private SerialPort serialPort;
        private string serialPortName = "";
        private string defaultStr = "init text";
        private string successStr = "complete";
        private string failStr = "check the port again";
        public string portErrorMsg = defaultStr;

        public event PropertyChangedEventHandler PropertyChanged;

        public JigViewModel()
        {
            serialPort = new SerialPort();
            serialPort.BaudRate = 9600;
            serialPort.Parity = Parity.None;
            serialPort.StopBits = StopBits.One;
            serialPort.DataBits = 8;
        }

        public string SerialPortName
        {
            get => serialPortName;
            set
            {
                if (serialPortName != value)
                {
                    serialPortName = value;
                    Debug.WriteLine($"{serialPortName} is selected.");
                    OnPropertyChanged(nameof(SerialPortName));

                    serialPort.PortName = value;

                    if (!serialPort.IsOpen)
                    {
                        try
                        {
                            serialPort.Open();
                        
                            if(serialPort.IsOpen)
                            {
                                this.PortErrorMsg = successStr;
                            }
                        }
                        catch
                        {
                            this.PortErrorMsg = failStr;
                        }
                    }
                }
            }
        }

        public string PortErrorMsg
        {
            set
            {
                if (portErrorMsg != value)
                {
                    portErrorMsg = value;
                    Debug.WriteLine($"{portErrorMsg} is selected.");
                    OnPropertyChanged(nameof(PortErrorMsg));
                }
            }
            get
            {
                Debug.WriteLine("Message for checking whether get is working properly");
                return portErrorMsg;
            }
        }

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                Debug.WriteLine($"propertyName is {propertyName}");
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            else
            {
                Debug.WriteLine("PropertyChanged is null !");
            }
        }
    }
}

我期望xaml中的标签在PropertyChanged调用时更改。

w41d8nur

w41d8nur1#

从我的Angular 来看,创建了两个ViewModel,其中一个是在xaml中创建的:

<ContentPage.BindingContext>
    <vm:JigViewModel/>
</ContentPage.BindingContext>

在您的事件中创建另一个:

private void picker1_SelectedIndexChanged(object sender, EventArgs e)
{
    ViewModel vm = new ViewModel(); // i supposed it's JigViewModel, right?
    vm.SerialPortName = picker1.SelectedItem as string;
}

您的xaml视图绑定到第一个视图,当您触发picker1_SelectedIndexChanged时,它只创建一个新的ViewModel,与您的视图没有任何关系,因此PropertyChanged属性始终为null,您的标签无法更改。
在这里我给予你一些建议。在你的代码绑定。

public partial class MainPage : ContentPage
{

    JigViewModel vm;

    public MainPage()
    {
        InitializeComponent();
        vm = new JigViewModel();
        this.BindingContext = vm;
    }

    private void picker1_SelectedIndexChanged(object sender, EventArgs e)
    {
        vm.SerialPortName = picker1.SelectedItem as string;
    }

在你的xaml中,删除下面的代码:

<ContentPage.BindingContext>
    <vm:JigViewModel/>
</ContentPage.BindingContext>

我希望我的回答能对你有所帮助。

mspsb9vt

mspsb9vt2#

如果我在你家我会:
1.使用社区工具箱. MVVM。
1.使用注解将选取器的SelectedItem绑定到ObservableProperty。
1.如果需要,在部分空的OnSerialPortChanged(...)中编写一些代码。
你不需要这些事件,不需要手动调用方法,也不需要编写一行样板代码。

相关问题