在ViewModel值上找不到属性(.NET MAUI XAML)

xt0899hw  于 2023-06-19  发布在  .NET
关注(0)|答案(1)|浏览(116)

我在处理更新XAML时遇到问题。我正在使用一个库,它从UDP和代码中读取数据,并从数据包中解析数据,因此我正在尝试相应地更新我的XAML,目前只有一个属性。代码编译正常,应用程序也执行了,但是我的调试输出中充满了相同的警告,即在我的视图模型的值中找不到我要查找的属性。该值是结构的示例。有什么帮助吗?
这是我第一次处理MVVM,所以我还是有点困惑。
MainPage.xaml.cs

using F1Telemetry;
using System.Diagnostics;

namespace TestApp;

public partial class MainPage : ContentPage
{
    TelemetryViewModel telemetryViewModel;
    public MainPage()
    {
        InitializeComponent();

        F1TelemetryClient client = new F1TelemetryClient(20777);

        telemetryViewModel = new TelemetryViewModel();
        this.BindingContext = telemetryViewModel;

        client.OnCarTelemetryDataReceive += Client_OnCarTelemetryDataReceive;
    }

    private void Client_OnCarTelemetryDataReceive(PacketCarTelemetryData packet)
    {
        int playerIndex = packet.Header.playerCarIndex;

        CarTelemetryData carTelemetryData = packet.carTelemetryData[playerIndex];

        telemetryViewModel.Data = carTelemetryData;
    }
}

MainPage.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"
             xmlns:local="clr-namespace:TestApp"
             x:Class="TestApp.MainPage"
             xmlns:F1Telemetry="clr-namespace:F1Telemetry;assembly=F1Telemetry">

    <ContentPage.BindingContext>
        <local:TelemetryViewModel />
    </ContentPage.BindingContext>
    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">
            <Label
                BindingContext="{Binding Data}"
                Text="{Binding engineRPM}"
                FontSize="18"
                HorizontalOptions="Center" />

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

TelemetryViewModel.cs

using F1Telemetry;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace TestApp
{
    public class TelemetryViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private CarTelemetryData _data;

        public CarTelemetryData Data
        {
            get => _data;
            set
            {
                _data = value;
                OnPropertyChanged();
            }
        }

        public TelemetryViewModel()
        {
            this.Data = new CarTelemetryData();
        }

        private void OnPropertyChanged([CallerMemberName] string name = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

CarTelemetryData.cs(修剪了一些属性)

using System.Runtime.InteropServices;

namespace F1Telemetry
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct CarTelemetryData
    {
        public ushort speed;
        public float throttle;
        public float steer;
        public float brake;
        public byte clutch;
        public sbyte gear;
        public ushort engineRPM;
        public byte drs;
        public byte revLightsPercent;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public ushort[] brakesTemperature;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] tyresSurfaceTemperature;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] tyresInnerTemperature;
        public ushort engineTemperature;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public float[] tyresPressure;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] surfaceType;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct PacketCarTelemetryData
    {
        public PacketHeader Header;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)]
        public CarTelemetryData[] carTelemetryData;
        public ButtonFlags buttonStatus;
        public MFDPanel mfdPanelIndex;
        public MFDPanel mfdPanelIndexSecondaryPlayer;
        public sbyte suggestedGear;
    }
}

我检查了OnPropertyChanged()是否被调用,实际上它每次都被调用(实际上每秒60次),视图模型中的值似乎每次都在改变,出于某种原因(可能是一个愚蠢的原因)XAML假设我的值没有engineRPM属性。我也试过只使用{Binding Data.engineRPM},也不起作用。
先谢谢你了!

ccrfmcuu

ccrfmcuu1#

总的来说,你的代码有几个问题。
1.you 为您的页面设置了两次BindingContext,一次是在文件MainPage.xaml中:

<ContentPage.BindingContext>
    <local:TelemetryViewModel />
</ContentPage.BindingContext>

一个是在MainPage.xaml.cs的构造器中:

public partial class MainPage : ContentPage
{
    TelemetryViewModel telemetryViewModel;
    public MainPage()
    {
        InitializeComponent();

        F1TelemetryClient client = new F1TelemetryClient(20777);

        // set BindingContext here
        telemetryViewModel = new TelemetryViewModel();
        this.BindingContext = telemetryViewModel;

        client.OnCarTelemetryDataReceive += Client_OnCarTelemetryDataReceive;
    }

}

请删除上述方法之一,使用其中之一。
2.如果我们想将一个属性绑定到UI,我们通常需要确保它是这样的:

public ushort engineRPM {get;set;}

如果UI在更改属性值时刷新自己,我们还需要为模型实现接口INotifyPropertyChanged,并为我们想要更改值的属性调用方法OnPropertyChanged()

相关问题