C# + XAML - UI 在更改后没有得到更新

标签 c# wpf xaml user-interface template10

我想更新我的 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/

相关文章:

c# - C# 中的 "Class"和 "Private Class"声明有什么区别?

c# - WPF TabItem - 图像绑定(bind)

c# - 十进制到 ASCII 转换

c# - 如何使用 C# 和 WPF 编写 Windows 7 桌面小工具?

c# - 无法使用 Visual Studio 2012 RTM 在 Silverlight 5 项目中添加 XAML 断点

c# - 将 ICollectionView 转换为 List<T>

c# - 使用 C# 更新 facebook 状态

c# - web服务中文件下载多线程并发的问题

silverlight - 如何在绑定(bind)中将 TargetNullValue 设置为 Visibility.Collapsed

c# - Xamarin.Forms 动态布局取决于屏幕方向或大小