ViewModel 未更新表单 (Xamarin.Forms)
ViewModel not updating form (Xamarin.Forms)
我正在尝试让 ViewModel 更新 XAML 页面上的计数器,但无法弄清楚我做错了什么...
itemCount 的初始值显示良好,但每次递增后都不会更新。
这是 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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:local="clr-namespace:XamarinFormsTest01"
mc:Ignorable="d"
x:Class="XamarinFormsTest01.MainPage">
<StackLayout>
<Label x:Name="lblMain" Text="{Binding ItemCount}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" >
<Label.BindingContext>
<local:ItemCountViewModel />
</Label.BindingContext>
</Label>
<Button x:Name="BtnStart" Text="start" Pressed="BtnStart_Pressed" />
<Button x:Name="BtnStop" Text="stop" Pressed="BtnStop_Pressed" />
</StackLayout>
</ContentPage>
以及 ViewModel 源代码:
public class ItemCountViewModel : INotifyPropertyChanged
{
private static ItemCountViewModel instance = new ItemCountViewModel();
public static ItemCountViewModel GetInstance()
{
return instance;
}
int itemCount;
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public ItemCountViewModel()
{
itemCount = 0;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
itemCount++;
return true;
}
);
}
public int ItemCount
{
set
{
itemCount = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ItemCount"));
}
get
{
return itemCount;
}
}
}
您从 ItemCount.set
提高 PropertyChanged
,这是视图根据视图模型的状态更新所必需的。否则视图将不得不轮询状态更改,这会浪费资源,尤其是在我们希望避免因过度使用处理器而耗尽电池的移动设备上。
无论如何,当直接设置 itemCount
时,就像您在
中所做的那样
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
itemCount++;
return true;
}
ItemCount.set
永远不会被调用,因此 PropertyChanged
永远不会被引发,并且视图没有机会确定视图模型改变了它的状态。此外,我猜 ItemCount
必须在 UI 主线程中设置,因此你必须通过 Device.BeginInvokeOnMainThread
(see the documentation)
包装对 ItemCount.set
的调用
将代码更改为
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
Device.BeginInvokeOnMainThread (() =>
{
ItemCount++;
});
return true;
}
并且视图应该更新。
我正在尝试让 ViewModel 更新 XAML 页面上的计数器,但无法弄清楚我做错了什么...
itemCount 的初始值显示良好,但每次递增后都不会更新。
这是 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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:local="clr-namespace:XamarinFormsTest01"
mc:Ignorable="d"
x:Class="XamarinFormsTest01.MainPage">
<StackLayout>
<Label x:Name="lblMain" Text="{Binding ItemCount}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" >
<Label.BindingContext>
<local:ItemCountViewModel />
</Label.BindingContext>
</Label>
<Button x:Name="BtnStart" Text="start" Pressed="BtnStart_Pressed" />
<Button x:Name="BtnStop" Text="stop" Pressed="BtnStop_Pressed" />
</StackLayout>
</ContentPage>
以及 ViewModel 源代码:
public class ItemCountViewModel : INotifyPropertyChanged
{
private static ItemCountViewModel instance = new ItemCountViewModel();
public static ItemCountViewModel GetInstance()
{
return instance;
}
int itemCount;
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public ItemCountViewModel()
{
itemCount = 0;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
itemCount++;
return true;
}
);
}
public int ItemCount
{
set
{
itemCount = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ItemCount"));
}
get
{
return itemCount;
}
}
}
您从 ItemCount.set
提高 PropertyChanged
,这是视图根据视图模型的状态更新所必需的。否则视图将不得不轮询状态更改,这会浪费资源,尤其是在我们希望避免因过度使用处理器而耗尽电池的移动设备上。
无论如何,当直接设置 itemCount
时,就像您在
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
itemCount++;
return true;
}
ItemCount.set
永远不会被调用,因此 PropertyChanged
永远不会被引发,并且视图没有机会确定视图模型改变了它的状态。此外,我猜 ItemCount
必须在 UI 主线程中设置,因此你必须通过 Device.BeginInvokeOnMainThread
(see the documentation)
ItemCount.set
的调用
将代码更改为
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
Device.BeginInvokeOnMainThread (() =>
{
ItemCount++;
});
return true;
}
并且视图应该更新。