【问题标题】:INotifyPropertyChanged does not workINotifyPropertyChanged 不起作用
【发布时间】:2015-04-14 13:37:26
【问题描述】:

可能不是最好的解决方案,但我注意到我的应用程序的许多不同页面和用户控件使用相同的数据(主要是通过绑定),所以我做了以下类

public class GPSHelper : INotifyPropertyChanged
    {
        private double _speed;
        public double Speed
        {
            get
            {
                return _speed;
            }
            set
            {
                _speed = value;
                NotifyPropertyChanged("Speed");
            }
        }
        public double AvgSpeed { get; set; }
        public double MaxSpeed { get; set; }
        public double Distance { get; set; }
        public double Altitude { get; set; }
        public double Longtitude { get; set; }
        public double Latitude {get; set;}
        private int _locationChangedCounter;
        private Geolocator _locator; 
        public GPSHelper()
        {
            _locator = new Geolocator();
            _locator.MovementThreshold = 0.5;
            _locator.PositionChanged += locator_PositionChanged;
            MaxSpeed = 0;
            AvgSpeed = 0;
            Speed = 30; 
        }

        private async void locator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
        {

            Geoposition position = await _locator.GetGeopositionAsync();
            Geopoint point = args.Position.Coordinate.Point;
            //Speed = position.Coordinate.Speed.Value;
            Speed = 120; 
            Altitude = point.Position.Altitude;
            if(Speed > MaxSpeed)
            {
                MaxSpeed = Speed; 
            }
            AvgSpeed += Speed / _locationChangedCounter;
            _locationChangedCounter++;
        }

        private void NotifyPropertyChanged(string propertyname)
        {
            if(PropertyChanged!=null)
            {
                 PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
    }

在 App.xaml 中,我将类添加为资源,我不知道是否可以这样做,但这似乎仍然是个好主意。

<Application
    x:Class="SpeedometerGPS.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SpeedometerGPS"
    xmlns:helpers ="using:SpeedometerGPS.Helpers">
    <Application.Resources>
        <helpers:GPSHelper x:Key="GPSHelper" /> 
    </Application.Resources>
</Application>

我现在唯一的问题是 PropertyChanged 不起作用,它给出了一个非常正当的理由 - ,,应用程序调用了一个为不同线程编组的接口。”有什么建议可以解决它吗?

【问题讨论】:

    标签: c# xaml geolocation windows-phone-8.1


    【解决方案1】:

    问题在于传入的事件不在 GUI 线程上,而是在工作线程上。 然后,您正在操纵速度,我认为这是某些绑定的一部分。 如果它是某些绑定的一部分,则更新速度将对这些绑定产生影响,但这仅在 GUI 中发生更改时才有效。

    归根结底,您必须将速度的变化或整个事件分派给 GUI 线程。

    对 GUI 线程的调度解释如下: The application called an interface that was marshalled for a different thread in window 8

    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        Speed = 120; 
    });
    

    【讨论】:

    • 这是不是 windows phone 的东西没有调度绑定?我知道它会自动调度 WPF,但我也知道 WPF xaml 中的许多东西在 windows phone xaml 上不起作用。
    • 我知道调度程序,但是如果在我上面发布的代码中无法使用速度变化,我应该在哪里调度?
    • 在 WPF 中,大多数事件已经在 GUI 线程上,因此不需要调度,但在 windows phone 中,大多数事件不在 GUI 线程上。
    • DDavid,您是否点击了链接。它显示了如何调度。
    • @DDavid 您可能会在 private void NotifyPropertyChanged(string propertyname) 中调用调度程序,并在 UI 线程上调用 PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
    【解决方案2】:

    地理定位器文档说:

    “重要在访问用户位置之前调用RequestAccessAsync。此时,您的应用必须在前台,并且必须从UI线程调用RequestAccessAsync。直到用户授予您的应用对其位置的权限,您的应用才能' t 访问位置数据。”

    https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.geolocation.geolocator

    因此,您应该将 Geolocator 作为静态属性放在其他地方(例如 App.xaml.cs),并在获取任何事件之前从 UI 线程中的方法调用 RequestAccessAsync。

    【讨论】:

    • 地理定位器工作正常,错误显示在 NotifyPropertyChanged 方法中。
    • 是的,但是速度的变化发生在方法 locator_PositionChanged 中,该方法显然是从 UI 线程之外的另一个线程调用的(看到您的错误“应用程序调用了为不同线程编组的接口”)。这个方法是由 PositionChangedEvent 调用的。
    【解决方案3】:

    我自己解决了这个问题,将 Geolocator 作为 App.xaml.cs 中的静态成员,并首先在 OnLaunch() 中实际使用它,然后分配事件处理程序解决了一段时间的问题,但整个程序崩溃了一分钟左右后。谷歌搜索了几个小时后,结果发现为了按照我希望的方式在课堂上使用调度程序,你必须做这样的事情。不过,感谢大家的努力,无论您是否正在阅读。

    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority,() => {})
    

    【讨论】:

      猜你喜欢
      • 2018-03-19
      • 1970-01-01
      • 2011-06-26
      • 2011-11-26
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多