Xamarin,xaml 中的标签文本不会随着 MVVM Helpers 的属性更改而更改

Posted

技术标签:

【中文标题】Xamarin,xaml 中的标签文本不会随着 MVVM Helpers 的属性更改而更改【英文标题】:Xamarin, Label Text in xaml doesn't change on property changed WITH MVVM Helpers 【发布时间】:2022-01-11 22:30:19 【问题描述】:

在我的 Xaml 中,值仅在我进入 xaml 并执行以下操作时更新:

绑定使用.currentlevel->绑定使用.currentleve->绑定使用.currentlevel

但当use 变量在启动和从数据库中获取数据时更新时,我不知道为什么。

附:我在 xaml 文件中设置了 bindingcontext。

AboutPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="INWORK.Views.AboutPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:control="clr-namespace:ProgressRingControl.Forms.Plugin;assembly=ProgressRing.Forms.Plugin"
    xmlns:vm="clr-namespace:INWORK.ViewModels"
    Title="Binding Title"

    BackgroundImage="MainBackground.png">

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

    <ContentPage.Resources>
        <ResourceDictionary>
            <Color x:Key="Accent">#96d1ff</Color>
            <Color x:Key="Muscular">#E76F51</Color>
            <Color x:Key="Cardio">#429EA6</Color>
        </ResourceDictionary>
    </ContentPage.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="3*" />
            <RowDefinition Height="1*" />
            <RowDefinition Height="1*" />
            <RowDefinition Height="1.15*" />
        </Grid.RowDefinitions>

        <Ellipse
            Grid.Row="1"
            Fill="Gray"
            HeightRequest="160"
            HorizontalOptions="Center"
            Stroke="#FFFF9900"
            VerticalOptions="Center"
            WidthRequest="160" />
        <control:ProgressRing
            Grid.Row="1"
            HeightRequest="100"
            Progress="Binding use.muscularprogress"
            RingProgressColor="StaticResource Muscular"
            RingThickness="20"
            Scale="1"
            WidthRequest="100"
            class="pro" />
        <control:ProgressRing
            Grid.Row="1"
            HeightRequest="100"
            Progress="Binding use.cardioprogress"
            RingProgressColor="StaticResource Cardio"
            RingThickness="20"
            Scale="0.85"
            class="pro" />
        <StackLayout Grid.Row="1" VerticalOptions="Center">
            <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
                <Label
                x:Name="Level"
                FontAttributes="Bold"
                FontSize="20"
                HorizontalOptions="CenterAndExpand"
                Text="Level "
                TextColor="Black" />
                <Label
                FontAttributes="Bold"
                FontSize="20"
                HorizontalOptions="CenterAndExpand"
                Text="Binding use.currentlevel"
                TextColor="Black" />
                <Button Command="Binding GoInfoCommand"></Button>
            </StackLayout>

            <Label
                x:Name="Totalprocent"
                FontAttributes="Bold"
                FontSize="20"
                HorizontalOptions="CenterAndExpand"
                Text="0%"
                TextColor="Black" />
        </StackLayout>

        <Grid Grid.Row="4">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <StackLayout Grid.Column="0">
                <Label
                    Padding="2"
                    FontAttributes="Bold"
                    FontSize="20"
                    HorizontalOptions="Center"
                    Text="Muscular"
                    TextColor="StaticResource Muscular" />
                <StackLayout HorizontalOptions="Center" Orientation="Horizontal">
                    <Label
                        FontAttributes="Bold"
                        FontSize="20"
                        Text="Binding use.muscularprogress"
                        TextColor="Black" />
                    <Label
                        FontAttributes="Bold"
                        FontSize="20"
                        Text="%"
                        TextColor="Black" />
                </StackLayout>
            </StackLayout>
            <StackLayout Grid.Column="2">
                <Label
                    x:Name="easier"
                    FontAttributes="Bold"
                    FontSize="20"
                    HorizontalOptions="Center"
                    Text="Cardio"
                    TextColor="StaticResource Cardio" />
                <StackLayout HorizontalOptions="Center" Orientation="Horizontal">
                    <Label
                        FontAttributes="Bold"
                        FontSize="20"
                        Text="Binding use.cardioprogress"
                        TextColor="Black" />
                    <Label
                        FontAttributes="Bold"
                        FontSize="20"
                        Text="%"
                        TextColor="Black" />
                </StackLayout>
            </StackLayout>
        </Grid>
    </Grid>
</ContentPage>

LevelProgress.cs 模型

using SQLite;
using System;
using System.Collections.Generic;
using System.Text;

namespace INWORK.Models

    public class LevelProgress
    
        [PrimaryKey, AutoIncrement]
        public int Id  get; set; 

        public int currentlevel  get; set; 

        public bool pushups;
        public bool squats;
        public bool pullups;
        public bool splitsquats;
        public bool stepups;
        public bool tricepdips;
        public bool legraises;

        //Cardio section
        public bool running;

        public bool intervals;
        public double muscularprogress  get; set; 
        public double cardioprogress  get; set; 
    

服务用于访问本地数据库

using INWORK.Models;
using SQLite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Essentials;

namespace INWORK.Services

    internal class DataStorage
    
        private static SQLiteAsyncConnection db;

        private static async Task Init()
        
            if (db != null)
                return;
            var databasePath = Path.Combine(FileSystem.AppDataDirectory, "test2.db");
            db = new SQLiteAsyncConnection(databasePath);
            await db.CreateTableAsync<LevelProgress>();
            await db.CreateTableAsync<Overview>();
        

        public static async Task FirstCreation()
        
            await Init();

            LevelProgress LevelProgress = new LevelProgress()
            
                currentlevel = 1,
                cardioprogress = 0,
                muscularprogress = 0,
                pushups = false,
                squats = false,
                pullups = false,
                splitsquats = false,
                stepups = false,
                tricepdips = false,
                legraises = false
            ;
            await db.InsertAsync(LevelProgress);
        

        public static async Task EditProgress(LevelProgress usehere)
        
            await Init();

            await db.UpdateAsync(new LevelProgress()
            
                Id = 1,
                currentlevel = usehere.currentlevel,
                muscularprogress = usehere.muscularprogress,
                pushups = usehere.pushups,
                squats = usehere.squats,
                pullups = usehere.pullups,
                splitsquats = usehere.splitsquats,
                stepups = usehere.stepups,
                tricepdips = usehere.tricepdips,
                legraises = usehere.legraises,
                cardioprogress = usehere.cardioprogress,
                running = usehere.running,
                intervals = usehere.intervals
            );
        

        public static async Task FinishWorkout()
        
        

        public static async Task<LevelProgress> GetProgress()
        
            await Init();
            var levelProgress = await db.Table<LevelProgress>().FirstOrDefaultAsync();
            //var levelProgress = await db.Table<LevelProgress>().ToListAsync();
            return levelProgress;
        

        public static async Task AddWorkout(string _Workout_type, int _Result, DateTime _Date)
        
            await Init();

            Overview Overview = new Overview()
            
                Workout_type = _Workout_type,
                Result = _Result,
                Date = _Date
            ;

            await db.InsertAsync(Overview);
        

        public static async Task<IEnumerable<Overview>> GetOverview(string type)
        
            await Init();

            IEnumerable<Overview> overview;
            if (type == "Running" || type == "Intervals")
            
                overview = await db.Table<Overview>().Where(v => v.Workout_type == "Running" || v.Workout_type == "Intervals").ToListAsync();
            
            else
            
                overview = await db.Table<Overview>().Where(v => v.Workout_type != "Running" || v.Workout_type != "Intervals").ToListAsync();
            

            return overview;
        
    

关于ViewModel

using INWORK.Models;
using INWORK.Services;
using MvvmHelpers;
using System;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace INWORK.ViewModels

    public class AboutViewModel : ViewModelBase
    
        public ICommand GoInfoCommand  get; set; 

        public AboutViewModel()
        
            Title = "About";
            OpenWebCommand = new Command(async () => await Browser.OpenAsync("https://aka.ms/xamarin-quickstart"));
            //Command = "Binding OpenWebCommand
            Task.Run(async () => await Loadup());
            
            //use.currentlevel = use.currentlevel;
        

        private LevelProgress pp;
        private LevelProgress _use;

        public LevelProgress use
        
            get => _use;
            set
            
                _use = value;
                OnPropertyChanged();
            
        

        public async Task Loadup()
        
            _use = new LevelProgress();
            var temps = await DataStorage.GetProgress();
            use = temps;
            //await ProgressTracker.AddWorkout("Ŗunning",2, DateTime.Today);

            if (use.currentlevel == 0)
            
                await DataStorage.FirstCreation();
                Loadup();
            
        

        public ICommand OpenWebCommand  get; 
    

【问题讨论】:

【参考方案1】:

是的,如果我们想在对象use中更改字段(muscularprogress,cardioprogress)后更新UI,我们需要使类LevelProgress实现接口INotifyPropertyChanged

既然你有基类ViewModelBase,我们可以这样做:

public class LevelProgress: ViewModelBase

    [PrimaryKey, AutoIncrement]
    public int Id  get; set; 

    public int currentlevel  get; set; 

    public bool pushups;
    public bool squats;
    public bool pullups;
    public bool splitsquats;
    public bool stepups;
    public bool tricepdips;
    public bool legraises;

    //Cardio section
    public bool running;

    public bool intervals;

    //public double muscularprogress  get; set; 

    private double _muscularprogress;
    public double muscularprogress
    
        get => _muscularprogress;
        set  SetProperty(ref _muscularprogress, value); 
    


    //public double cardioprogress  get; set; 

    private double _cardioprogress;
    public double cardioprogress
    
        get => _cardioprogress;
        set  SetProperty(ref _cardioprogress, value); 
    

注意:

作为测试,我为它创建了一个具有特殊值的假对象,并在开始时将其值分配为use,之后我们更改它的值,UI可以自动刷新。

       private void test(object obj)
    
        use.muscularprogress = 98.8;
        use.cardioprogress = 12.9;
    

【讨论】:

嗨@Emils Legzdins,我已经好几天没有收到你的消息了。如果有什么我可以帮助的,请告诉我。

以上是关于Xamarin,xaml 中的标签文本不会随着 MVVM Helpers 的属性更改而更改的主要内容,如果未能解决你的问题,请参考以下文章

OnPropertyChanged 不会与标签文本一起触发

Xamarin.Forms 在 XAML 中使用局部变量

Xamarin Forms 将属性绑定到标签的文本

Xamarin iOS - XAML IsVisible 绑定在 ItemsSource 更改时不会更新

XAML中的Xamarin.Forms ListView AutoHeight

Xamarin.Forms XAML的辅助功能Code Snippet