![](/img/trans.png)
[英]Xamarin Forms Button IsVisible Binding not Working on Android
[英]Binding values not working on Xamarin Forms
我正在使用 MVVM 在 Xamarin Forms 上構建應用程序。 問題是當我運行應用程序時,數據沒有出現,值是默認值。 但是,如果我在 Xaml 文件中以綁定屬性的名稱更改某些內容,則該值將更新並顯示為應有的樣子,而無需重新啟動應用程序。 我提到我在 ViewModel 中初始化了 BindingContext。
這是代碼:
視圖模型:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using XamarinApp.Services;
using XamarinApp.Views.Month;
namespace XamarinApp.ViewModels.Month
{
public class DefaultScreenViewModel : BaseViewModel
{
private readonly IMonthService _monthService;
public decimal budget;
public decimal spendings;
public decimal economies;
public decimal percent;
public DefaultScreenViewModel(IMonthService monthService)
{
_monthService = monthService;
UpdateBudgetCommand = new Command(async () => await GoToUpdateBudget());
Title= "My Money";
}
public async void GetDefaultScreen()
{
try
{
var screen = await _monthService.GetDefaultScreen();
budget = screen.Budget;
economies = screen.Economies;
spendings = screen.Spendings;
percent = spendings/budget;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public decimal Budget
{
get => budget;
set => OnPropertyChanged(nameof(Budget));
}
public decimal Spendings
{
get => spendings;
set => OnPropertyChanged(nameof(Spendings));
}
public decimal Economies
{
get => economies;
set => OnPropertyChanged(nameof(Economies));
}
public decimal Percent
{
get => percent;
set => OnPropertyChanged(nameof(Percent));
}
private async Task GoToUpdateBudget()
=> await Shell.Current.GoToAsync(nameof(UpdateBudgetPage));
public ICommand UpdateBudgetCommand { get; }
}
}
Xaml 文件:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:month="clr-namespace:XamarinApp.ViewModels.Month"
x:Class="XamarinApp.Views.Month.DefaultScreenPage"
BackgroundColor="{StaticResource BackgroundColor}"
Title="{Binding Title}">
<ContentPage.Content>
<StackLayout>
<Frame Padding="30" Margin="30" BackgroundColor="{StaticResource Primary}">
<StackLayout>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Vertical" FlexLayout.AlignSelf="Start" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Spendings}" FontSize="Subtitle" VerticalOptions="FillAndExpand" />
<Label Text="Spendings" FontSize="Subtitle" VerticalOptions="FillAndExpand"/>
</StackLayout>
<StackLayout Orientation="Vertical" FlexLayout.AlignSelf="End" HorizontalOptions="End">
<Label Text="{Binding Budget}" FontSize="Subtitle" VerticalOptions="FillAndExpand" />
<Label Text="Budget" FontSize="Subtitle" VerticalOptions="FillAndExpand"/>
</StackLayout>
</StackLayout>
<ProgressBar Progress="{Binding Percent}" BackgroundColor="#69B811" ProgressColor="#750909" FlexLayout.AlignSelf="Center" Margin="10"/>
<Label/>
<Label Text="Current Month Savings: " />
<Label Text="{Binding Economies}"/>
</StackLayout>
</Frame>
<Button Text="Update your budget" Command="{Binding UpdateBudgetCommand}" Margin="20,40,20,0" CornerRadius="10"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Xaml.cs 文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using XamarinApp.ViewModels.Month;
namespace XamarinApp.Views.Month
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DefaultScreenPage : ContentPage
{
public readonly DefaultScreenViewModel _defaultScreenViewModel;
public DefaultScreenPage()
{
InitializeComponent();
_defaultScreenViewModel = Startup.Resolve<DefaultScreenViewModel>();
BindingContext = _defaultScreenViewModel;
}
protected override void OnAppearing()
{
_defaultScreenViewModel?.GetDefaultScreen();
}
}
}
和 BaseViewModel:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;
using XamarinApp.Models;
using XamarinApp.Services;
namespace XamarinApp.ViewModels
{
public class BaseViewModel : INotifyPropertyChanged
{
public IDataStore<Item> DataStore => DependencyService.Get<IDataStore<Item>>();
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
string title = string.Empty;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}
protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
GetDefaultScreen
正在設置公共字段的值
var screen = await _monthService.GetDefaultScreen();
budget = screen.Budget;
economies = screen.Economies;
spendings = screen.Spendings;
percent = spendings/budget;
相反,您需要設置公共屬性的值
var screen = await _monthService.GetDefaultScreen();
Budget = screen.Budget;
Economies = screen.Economies;
Spendings = screen.Spendings;
Percent = spendings/budget;
回復“我忘記輸入字段 = 值”(在設置器中)。
這是一種簡化設置器的方法。 在一些 mvvm 庫中使用,並顯示在Xamarin Forms 綁定模式中。
在您的BaseViewModel
class 中,添加此方法:
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
那么每個屬性就是:
private decimal budget;
public decimal Budget
{
get => budget;
set => SetProperty(ref budget, value);
}
注意:屬性名稱在編譯時通過可選第三個參數的[CallerMemberName]
屬性自動獲取。
注意:字段( budget
)通常是private
的。 沒有其他 class 應該使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.