我想更新我的 UI,但它没有得到更新,即使调用了 PropertyChanged
事件。在启动时我得到第一个值,但在更改后它不会更新。
在调试时,我可以看到值得到更新并且 PropertyChanged
事件被触发,但是 getter 没有被调用。
(顺便说一句:我是 C# 的新手,分别是 M-V-VM 概念。)
XAML
<Page.DataContext>
<vm:MainPageViewModel x:Name="ViewModel" />
</Page.DataContext>
...
<TextBlock x:Name="LatitudeVar" Text="{Binding LatitudeVar, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="79" Canvas.Left="189" Canvas.Top="38" />
C#(MainPageViewModel)
public class MainPageViewModel : ViewModelBase, INotifyPropertyChanged
{
private Session _session;
public MainPageViewModel()
{
_session = Session.Instance;
}
public static readonly MainPageViewModel Instance = new MainPageViewModel();
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
{
// App just started, so we get GPS access and eventually initialize the client
Session.InitializeClient();
await StartGpsDataService();
await Task.CompletedTask;
}
...
private string _latitude;
public string LatitudeVar
{
get { return _session.Latitude; }
set { _session.Latitude = value; NotifyPropertyChanged(); }
}
...
public async Task StartGpsDataService()
{
await Session.InitializeDataUpdate();
}
public new event PropertyChangedEventHandler PropertyChanged;
[Annotations.NotifyPropertyChangedInvocator]
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
C#( session )
public class Session : INotifyPropertyChanged
{
public static void InitializeClient()
{
MainPageViewModel mpvm = new MainPageViewModel();
_mpvm = MainPageViewModel.Instance;
}
private static Session _instance;
public static Session Instance
{
get
{
if (_instance == null)
{
_instance = new Session();
}
return _instance;
}
}
private static Session _sc;
internal static Session Sc
{
get { return _sc; }
set { _sc = value; }
}
private static MainPageViewModel _mpvm;
private string _latitude;
public string Latitude
{
get { return _latitude; }
set
{
if (_latitude == value) return; _latitude = value; RaiseOnPropertyChanged("Latitude"); }
}
...
public void UpdateGpsData(Geopoint point, Geopoint geopointOld)
{
_mpvm.LatitudeVar = point.Position.Latitude.ToString();
}
public static async Task InitializeDataUpdate()
{
Sc = Session.Instance;
Sc.StartTime = DateTime.Now;
Sc.GetPosition(Geoposition.Coordinate.Point);
}
public new event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void RaiseOnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
我之前尝试过的一些方法:
C#(MainPageViewModel)
private string _latitude;
public string LatitudeVar
{
get { return _latitude; }
set { _latitude = value; NotifyPropertyChanged("LatitudeVar"); }
}
结果:未显示值。
C#( session )
public void UpdateGpsData(Geopoint point, Geopoint geopointOld)
{
Latitude = point.Position.Latitude.ToString();
}
结果:值在启动时显示,但未更新。
编辑:找到解决方案: 一些代码排序,感谢提示 ;) 现在我的 Session.cs 是一个模型。所有相关方法现在都在 ViewModel 中。我注意到,只有一个实例存在:
public MainPageViewModel()
{
_session = Session.Instance;
_instance = this;
}
最佳答案
哇,这是一个非常人为的单例模式实现。
首先,在 Session.InitializeClient 中创建的 MainPageViewModel 实例不是 View 正在使用的实例。 XAML
<Page.DataContext>
<vm:MainPageViewModel x:Name="ViewModel" />
</Page.DataContext>
将实例化 MainPageViewModel 的新实例,因此代码
public void UpdateGpsData(Geopoint point, Geopoint geopointOld)
{
_mpvm.LatitudeVar = point.Position.Latitude.ToString();
}
不会影响 View 。
虽然我强烈建议您取消对 Session 的单例尝试并考虑使用消息传递模式在系统组件之间进行通信,但您应该能够通过将 Session 实例单例公开为只读属性来使您的代码正常工作在 MainPageViewModel 上并直接绑定(bind)到它,如下所示:
<TextBlock Text="{Binding Path=Session.Latitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
当然,这意味着您的 UI 正在直接写入系统中的单例组件,可能不希望在其中实现 INotifyPropertyChanged。
按照建议,我强烈建议重新构建和删除单例和/或在系统组件之间采用消息传递。
关于C# + XAML - UI 在更改后没有得到更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39305633/