Xamarin窗体-强制控件刷新绑定中的值



给定以下ViewModel。。。

public class NameEntryViewModel 
{
public NameEntryViewModel()
{
Branding = new Dictionary<string, string>();
Branding.Add("HeaderLabelText", "Welcome to the app");
}
public Dictionary<string, string> Branding { get; set; }
}

已绑定到页面。。。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Monaco.Forms.Views.NameEntryPage">
<Label Text="{Binding Branding[HeaderLabelText]}" />
</ContentPage>

当页面出现时,标签将显示文本"欢迎使用该应用程序"。这非常有效,符合我们定制和全球化应用程序的计划。在本例中,品牌字典是静态设置的,但在现实世界中,它是由来自服务调用的数据初始化的。

然而,如果用户想将语言切换为西班牙语,我们需要每个绑定标签更新为新值。重置Branding字典并用西班牙语翻译填充它很容易,但我们如何才能强制控件从其绑定源进行刷新?

我在这里试图避免双向数据绑定b/c我们不希望为控件的每个Text属性创建后备属性的代码开销。因此,我们正在绑定一本价值观词典。

答案

我接受了下面的答案,但我没有使用传统的属性设置器。相反,当用户想要切换不同的语言时,我们现在有了一个集中的处理程序,它可以重新填充字典,然后通知字典的更改。我们正在使用MVVMCross,但您可以转换为标准表格。。。

public MvxCommand CultureCommand
{
get
{
return new MvxCommand(async () =>
{
_brandingService.ToggleCurrentCulture();
await ApplyBranding(); // <-- this call repopulates the Branding property
RaisePropertyChanged(() => Branding);
});
}
}

正如@BillReiss所提到的,您需要使用OnPropertyChanged事件来继承此类的NameEntryViewModel:

public class BaseViewModel : INotifyPropertyChanged
{
protected BaseViewModel ()
{
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler (this, new PropertyChangedEventArgs (propertyName));
}
}

创建一个私人财产,你可以将其分配给你的公共财产,比如:

Dictionary<string, string> _branding = new Dictionary<string, string>();
public Dictionary<string, string> Branding
{
get
{
return _branding;
}
set
{
_branding = value;
OnPropertyChanged(nameof(Branding));
}
}

每次设置Branding属性时,它都会让视图知道发生了变化有时如果在后台线程上执行此操作,则必须使用Device.BeginInvokeOnMainThread()

在BaseViewModel类中有一个方法:

protected bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null) {}

类似:

string title = string.Empty;
public string Title
{
get { return title; }
set { SetProperty(ref title, value); }
}

在继承的视图模型类的setter属性中使用SetProperty。然后它就会起作用。INotifyPropertyChanged已在BaseViewModel中实现。所以这里没有什么可改变的。

最新更新