Xamarin, Текст метки в xaml не меняется при изменении свойства С ПОМОЩЬЮ помощников MVVM

#c# #xaml #xamarin #android-databinding

#c# #xaml #xamarin #android-привязка данных

Вопрос:

В моем Xaml значения обновляются только тогда, когда я захожу в xaml и делаю это, например:

{Использование привязки.текущий уровень}-gt;{Использование привязки.текущий уровень}-gt;gt;{Использование привязки.текущий уровень}

но не тогда, когда use переменная обновляется при запуске и извлечении данных из базы данных, я не могу понять, почему.

P.S. я установил bindingcontext в файле xaml.

О странице.xaml

 lt;?xml version="1.0" encoding="utf-8" ?gt; lt;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"gt;   lt;ContentPage.BindingContextgt;  lt;vm:AboutViewModel /gt;  lt;/ContentPage.BindingContextgt;   lt;ContentPage.Resourcesgt;  lt;ResourceDictionarygt;  lt;Color x:Key="Accent"gt;#96d1fflt;/Colorgt;  lt;Color x:Key="Muscular"gt;#E76F51lt;/Colorgt;  lt;Color x:Key="Cardio"gt;#429EA6lt;/Colorgt;  lt;/ResourceDictionarygt;  lt;/ContentPage.Resourcesgt;   lt;Gridgt;  lt;Grid.RowDefinitionsgt;  lt;RowDefinition Height="1*" /gt;  lt;RowDefinition Height="3*" /gt;  lt;RowDefinition Height="1*" /gt;  lt;RowDefinition Height="1*" /gt;  lt;RowDefinition Height="1.15*" /gt;  lt;/Grid.RowDefinitionsgt;   lt;Ellipse  Grid.Row="1"  Fill="Gray"  HeightRequest="160"  HorizontalOptions="Center"  Stroke="#FFFF9900"  VerticalOptions="Center"  WidthRequest="160" /gt;  lt;control:ProgressRing  Grid.Row="1"  HeightRequest="100"  Progress="{Binding use.muscularprogress}"  RingProgressColor="{StaticResource Muscular}"  RingThickness="20"  Scale="1"  WidthRequest="100"  class="pro" /gt;  lt;control:ProgressRing  Grid.Row="1"  HeightRequest="100"  Progress="{Binding use.cardioprogress}"  RingProgressColor="{StaticResource Cardio}"  RingThickness="20"  Scale="0.85"  class="pro" /gt;  lt;StackLayout Grid.Row="1" VerticalOptions="Center"gt;  lt;StackLayout Orientation="Horizontal" HorizontalOptions="Center"gt;  lt;Label  x:Name="Level"  FontAttributes="Bold"  FontSize="20"  HorizontalOptions="CenterAndExpand"  Text="Level "  TextColor="Black" /gt;  lt;Label  FontAttributes="Bold"  FontSize="20"  HorizontalOptions="CenterAndExpand"  Text="{Binding use.currentlevel}"  TextColor="Black" /gt;  lt;Button Command="{Binding GoInfoCommand}"gt;lt;/Buttongt;  lt;/StackLayoutgt;   lt;Label  x:Name="Totalprocent"  FontAttributes="Bold"  FontSize="20"  HorizontalOptions="CenterAndExpand"  Text="0%"  TextColor="Black" /gt;  lt;/StackLayoutgt;   lt;Grid Grid.Row="4"gt;  lt;Grid.ColumnDefinitionsgt;  lt;ColumnDefinition Width="1*" /gt;  lt;ColumnDefinition Width="1*" /gt;  lt;ColumnDefinition Width="1*" /gt;  lt;/Grid.ColumnDefinitionsgt;  lt;StackLayout Grid.Column="0"gt;  lt;Label  Padding="2"  FontAttributes="Bold"  FontSize="20"  HorizontalOptions="Center"  Text="Muscular"  TextColor="{StaticResource Muscular}" /gt;  lt;StackLayout HorizontalOptions="Center" Orientation="Horizontal"gt;  lt;Label  FontAttributes="Bold"  FontSize="20"  Text="{Binding use.muscularprogress}"  TextColor="Black" /gt;  lt;Label  FontAttributes="Bold"  FontSize="20"  Text="%"  TextColor="Black" /gt;  lt;/StackLayoutgt;  lt;/StackLayoutgt;  lt;StackLayout Grid.Column="2"gt;  lt;Label  x:Name="easier"  FontAttributes="Bold"  FontSize="20"  HorizontalOptions="Center"  Text="Cardio"  TextColor="{StaticResource Cardio}" /gt;  lt;StackLayout HorizontalOptions="Center" Orientation="Horizontal"gt;  lt;Label  FontAttributes="Bold"  FontSize="20"  Text="{Binding use.cardioprogress}"  TextColor="Black" /gt;  lt;Label  FontAttributes="Bold"  FontSize="20"  Text="%"  TextColor="Black" /gt;  lt;/StackLayoutgt;  lt;/StackLayoutgt;  lt;/Gridgt;  lt;/Gridgt; lt;/ContentPagegt;  

Модель 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; }  } }  

Service for accsessing local database

 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.CreateTableAsynclt;LevelProgressgt;();  await db.CreateTableAsynclt;Overviewgt;();  }   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 Tasklt;LevelProgressgt; GetProgress()  {  await Init();  var levelProgress = await db.Tablelt;LevelProgressgt;().FirstOrDefaultAsync();  //var levelProgress = await db.Tablelt;LevelProgressgt;().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 Tasklt;IEnumerablelt;Overviewgt;gt; GetOverview(string type)  {  await Init();   IEnumerablelt;Overviewgt; overview;  if (type == "Running" || type == "Intervals")  {  overview = await db.Tablelt;Overviewgt;().Where(v =gt; v.Workout_type == "Running" || v.Workout_type == "Intervals").ToListAsync();  }  else  {  overview = await db.Tablelt;Overviewgt;().Where(v =gt; v.Workout_type != "Running" || v.Workout_type != "Intervals").ToListAsync();  }   return overview;  }  } }  

AboutViewModel

 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 () =gt; await Browser.OpenAsync("https://aka.ms/xamarin-quickstart"));  //Command = "{Binding OpenWebCommand}  Task.Run(async () =gt; await Loadup());    //use.currentlevel = use.currentlevel;  }   private LevelProgress pp;  private LevelProgress _use;   public LevelProgress use  {  get =gt; _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:

Да,если мы хотим обновить пользовательский интерфейс после изменения поля( muscularprogress , cardioprogress ) в объекте use , нам нужно создать 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 =gt; _muscularprogress;  set { SetProperty(ref _muscularprogress, value); }  }    //public double cardioprogress { get; set; }   private double _cardioprogress;  public double cardioprogress  {  get =gt; _cardioprogress;  set { SetProperty(ref _cardioprogress, value); }  } }  

Примечание:

В качестве теста я создал поддельный объект со специальным значением для него и назначил ему значение use в начале , после этого мы изменили его значение,и пользовательский интерфейс мог обновляться автоматически.

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

Комментарии:

1. Привет @Эмиль Легздинс , я не получал от тебя вестей уже пару дней. Пожалуйста, дайте мне знать, если я могу чем-то помочь здесь.