C# Xamarin表单MVVM更新不适用于UWP

C# Xamarin表单MVVM更新不适用于UWP,c#,mvvm,xamarin.forms,xamarin.uwp,C#,Mvvm,Xamarin.forms,Xamarin.uwp,我有以下代码: Device.StartTimer(TimeSpan.FromSeconds(1), () => { foreach (var detail in Customer.Details.Where(p => new string[] { "Queue", "Wating"}.Contains(p.Status))) { detail.HasTimer = true; detail.Time =

我有以下代码:

 Device.StartTimer(TimeSpan.FromSeconds(1),
     () =>
     {

     foreach (var detail in Customer.Details.Where(p => new string[] { "Queue", "Wating"}.Contains(p.Status)))
     {
         detail.HasTimer = true;
         detail.Time = detail.Time.Add(TimeSpan.FromSeconds(1));

     }
     return true;
     });
这段代码在我将其部署到android时运行良好,但在UWP中,信息只是在UI中被删除

我还尝试使用methdo Device.BeginInvokeMainThread,但得到了相同的结果

每个属性都实现INotifyPropertyChanged,详细信息是一个可观察集合,它也实现INotifyPropertyChanged

我正在使用Visual Studio 2017社区

XAML如下所示:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Bulingo.CCC.Mobile.Views.TicketDigital">
  <ContentView.Content>
    <StackLayout >
      <StackLayout.VerticalOptions>
        <LayoutOptions Alignment="Center">

        </LayoutOptions>
      </StackLayout.VerticalOptions>

      <Button IsVisible="{Binding MostrarBoton}"
            Text="Leer Código"
            VerticalOptions="Center"
            HorizontalOptions="Center"
            TextColor="White"          
            BackgroundColor="#77D065"
            Command="{Binding ReadQRCodeCommand}"/>

      <Label FontAttributes="Bold"
         TextColor="Red"
         Text="El Código QR leído no es válido."
         IsVisible="{Binding MostrarErrorQrCode}"/>
      <Label FontAttributes="Bold"
         TextColor="Red"
         Text="Por favor verifique su conexión de red."
         IsVisible ="{Binding MostrarErrorConexion}"
           />
      <StackLayout VerticalOptions="FillAndExpand" IsVisible="{Binding MostrarServicios}">

        <Image Aspect="Fill">
          <Image.Source>
            <UriImageSource Uri="{Binding LogoUrl}" />
          </Image.Source>
        </Image>
        <StackLayout Orientation="Horizontal">
          <Label FontSize="Large">Número</Label>
          <Label Text="{Binding Cliente.Numero}" FontSize="Large"/>
        </StackLayout>


        <ListView ItemsSource="{Binding Cliente.Detalles}"  SeparatorColor="Yellow" RowHeight="160">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell BindingContext="{Binding}" >
                <Frame OutlineColor="Accent"  >
                  <ContentView Padding="1" Margin="2"  >
                    <StackLayout   >
                      <Label Text="{Binding Servicio}" FontSize="Medium"/>
                      <StackLayout Orientation="Horizontal"  >
                        <Label Text="Sala de Espera"/>
                        <Label Text="{Binding SalaEspera}" HorizontalOptions="End"/>
                      </StackLayout>
                      <StackLayout Orientation="Horizontal"   >
                        <Label Text="Tiempo Transcurrido"/>
                        <Label  Text="{Binding TiempoTranscurridoText}" TextColor="{Binding TiempoTranscurridoColor}"/>
                      </StackLayout>
                      <StackLayout Orientation="Horizontal"  >
                        <Label Text="Personas delante"/>
                        <Label Text="{Binding TotalEnCola}"/>
                      </StackLayout>
                      <StackLayout Orientation="Horizontal"  >
                        <Label Text="Estado"/>
                        <Label Text="{Binding Estado}" FontAttributes="Bold"/>
                      </StackLayout>
                    </StackLayout>
                  </ContentView>
                </Frame>

              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>


      </StackLayout>

      <StackLayout VerticalOptions="FillAndExpand" IsVisible="{Binding MostrarFormularioEncuesta}">
        <Button HorizontalOptions="End"
          Command="{Binding CancelSurveyCommand}"
          Text="No quiero llenar la encuesta..."/>
        <Button Command="{Binding SaveSurveyCommand}" Text="Enviar"
             TextColor="White"
             BackgroundColor="#77D065"
             HorizontalOptions="End"/>
        <TableView Intent="Form">
          <TableRoot Title="Llenar Encuesta" BindingContext="{Binding Encuesta}">

            <TableSection Title="Método preferido">
              <ViewCell>
                <Picker SelectedIndex="{Binding BetterOrWorseInt}">
                  <Picker.Items>
                    <x:String>No estoy Seguro</x:String>
                    <x:String>Sin Sistema</x:String>
                    <x:String>Con Sistema</x:String>
                  </Picker.Items>
                </Picker>
              </ViewCell>
            </TableSection>
            <TableSection Title="Con el nuevo sistema, ¿la atención es más rápida o más lenta?">
              <ViewCell>
                <Picker SelectedIndex="{Binding SpeedInt}">
                  <Picker.Items>
                    <x:String>No estoy Seguro</x:String>
                    <x:String>Más lenta</x:String>
                    <x:String>Más rápida</x:String>
                  </Picker.Items>
                </Picker>
              </ViewCell>
            </TableSection>
            <TableSection Title="¿Desearía que instalemos el sistema en otras áreas o sucursales?">
              <ViewCell>
                <Picker SelectedIndex="{Binding ExpandInt}">
                  <Picker.Items>
                    <x:String>No estoy Seguro</x:String>
                    <x:String>No, no me gustaría</x:String>
                    <x:String>Sí, me gustaría</x:String>
                  </Picker.Items>
                </Picker>
              </ViewCell>
            </TableSection>
            <TableSection Title="¿Qué piensa de la calidad del nuevo sistema?">
              <ViewCell>
                <StackLayout HorizontalOptions="Fill">
                  <AbsoluteLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
                    <Slider Minimum="0" Maximum="5" WidthRequest="200" Value="{Binding QualityDouble}" Scale="1"
          AbsoluteLayout.LayoutBounds="0, 0.5"
          AbsoluteLayout.LayoutFlags="PositionProportional"
                      />
                    <Label Text="{Binding QualityText}" HorizontalOptions="Center" HorizontalTextAlignment="Center"
         AbsoluteLayout.LayoutBounds="0, 1"
         AbsoluteLayout.LayoutFlags="PositionProportional"
                         />
                  </AbsoluteLayout>
                </StackLayout>
              </ViewCell>
            </TableSection>
            <TableSection Title="¿Qué tan fácil es adaptarse al nuevo sistema?">
              <ViewCell>
                <StackLayout HorizontalOptions="Fill">
                  <AbsoluteLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
                    <Slider Minimum="0" Maximum="5" WidthRequest="200" Value="{Binding EasinessDouble}" Scale="1"
          AbsoluteLayout.LayoutBounds="0, 0.5"
          AbsoluteLayout.LayoutFlags="PositionProportional"
                      />
                    <Label Text="{Binding EasinessText}" HorizontalOptions="Center" HorizontalTextAlignment="Center"
         AbsoluteLayout.LayoutBounds="0, 1"
         AbsoluteLayout.LayoutFlags="PositionProportional"
                         />
                  </AbsoluteLayout>
                </StackLayout>
              </ViewCell>
            </TableSection>
            <TableSection Title="Sugerencias para el Sistema">
              <ViewCell >
                <Editor Text="{Binding NotesForBulingo}" HeightRequest="100" />


              </ViewCell>
            </TableSection>
            <TableSection Title="Sugerencias general">
              <ViewCell>
                <Editor Text="{Binding NotesForClient}" HeightRequest="100"/>
              </ViewCell>
            </TableSection>

          </TableRoot>
        </TableView>

      </StackLayout>

      <StackLayout VerticalOptions="FillAndExpand" IsVisible="{Binding MostrarAgradecimiento}">
        <Label FontSize="Large"
         FontAttributes="Bold"
         Text="¡Gracias por usar nuestros servicios y gracias por llenar nuestra encuesta!"></Label>

        <Image Aspect="AspectFill">
          <Image.Source>
            <UriImageSource Uri="{Binding LogoUrl}" />
          </Image.Source>
        </Image>
        <StackLayout Orientation="Horizontal">
          <Label FontSize="Large">Número</Label>
          <Label Text="{Binding Cliente.Numero}" FontSize="Large"/>
        </StackLayout>


        <ListView ItemsSource="{Binding Cliente.Detalles}"  SeparatorColor="Yellow" RowHeight="160">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell BindingContext="{Binding}" >
                <Frame OutlineColor="Accent"  >
                  <ContentView Padding="1" Margin="2"  >
                    <StackLayout   >
                      <Label Text="{Binding Servicio}" FontSize="Medium"/>
                      <StackLayout Orientation="Horizontal"  >
                        <Label Text="Sala de Espera"/>
                        <Label Text="{Binding SalaEspera}" HorizontalOptions="End"/>
                      </StackLayout>
                      <StackLayout Orientation="Horizontal"   >
                        <Label Text="Tiempo Transcurrido"/>
                        <Label  Text="{Binding TiempoTranscurridoText}" TextColor="{Binding TiempoTranscurridoColor}"/>
                      </StackLayout>
                      <StackLayout Orientation="Horizontal"  >
                        <Label Text="Personas delante"/>
                        <Label Text="{Binding TotalEnCola}"/>
                      </StackLayout>
                      <StackLayout Orientation="Horizontal"  >
                        <Label Text="Estado"/>
                        <Label Text="{Binding EstadoAtencion}" FontAttributes="Bold"/>
                      </StackLayout>
                    </StackLayout>

                  </ContentView>
                </Frame>

              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>

      </StackLayout>
      <ActivityIndicator Color="Red" IsRunning="{Binding IsBusy}" />
    </StackLayout>

  </ContentView.Content>
</ContentView>

努梅罗
没有estoy Seguro
Sin Sistema
共济会
没有estoy Seguro
玛斯·伦塔
马斯拉皮达
没有estoy Seguro
不,不,我是古斯塔里亚
我是古斯塔利亚
努梅罗
这是ViewModel,我删除了部分代码,因为我达到了这里的限制

    public class TicketDigitalViewModel : INotifyPropertyChanged
    {
        public static TimeSpan ServerClientTimeDifference { get; set; }
        private bool mostrarErrorQrCode;
        private static string surveyUri = "https://sdfghjklfghjkl.com/sadfkljsafdlkjroisdapi/api";
        private ClienteViewModel cliente;
        private bool isBusy;
        private string barCodeResult;
        private HubConnection connection;
        private IHubProxy ticketHub;
        private string connectionID;
        private ScreenStatuses screenStatus;
        private SampleViewModel encuesta;
        private bool isEncuestado;
        MobileBarcodeScanner scanner;
        bool scannerInitialized = false;
        private bool mostrarErrorConexion;
        internal void Resume()
        {
            initConnection();
        }

        public TicketDigitalViewModel()
        {
            Encuesta = new SampleViewModel();
            ReadQRCodeCommand = new Command(async () =>
                await ReadQRCode(),
                () => !IsBusy);
            SaveSurveyCommand = new Command(async () =>
                await SaveSurvey(Encuesta));
            CancelSurveyCommand = new Command(async () =>
                await CancelSurvey(),
                () => !IsBusy);
        }
        public Command CancelSurveyCommand { get; }
        public Command ReadQRCodeCommand { get; }
        public Command SaveSurveyCommand { get; }
        async Task<ZXing.Result> ReadQRCode()
        {
            if (!scannerInitialized)
            {
                scanner = new MobileBarcodeScanner();
                scannerInitialized = true;
            }
            BarCodeResult = null;
            var result = await scanner.Scan();
            BarCodeResult = result.Text;
            return result;
        }
        #region Data Properties.
        public ClienteViewModel Cliente
        {
            get
            {
                return cliente;
            }
            set
            {
                SetProperty(ref cliente, value);
                if (Cliente != null)
                {
                    if (Device.RuntimePlatform == "Windows")
                    {
                        Device.StartTimer(TimeSpan.FromSeconds(1),
                        () =>
                        {
                            foreach (var detalle in Cliente.Detalles.Where(p => new string[] { "EnCola", "Atendiendo", "EsperaCliente" }.Contains(p.Estado)))
                            {
                                Device.BeginInvokeOnMainThread(() =>
                                {
                                        detalle.HasTimer = true;
                                        detalle.TiempoTranscurrido = detalle.TiempoTranscurrido.Add(TimeSpan.FromSeconds(1));
                                });

                            }
                            return true;
                        });
                    }
                    else
                    {
                        Device.StartTimer(TimeSpan.FromSeconds(1),
                        () =>
                        {

                            foreach (var detalle in Cliente.Detalles.Where(p => new string[] { "EnCola", "Atendiendo", "EsperaCliente" }.Contains(p.Estado)))
                            {
                                detalle.HasTimer = true;
                                detalle.TiempoTranscurrido = detalle.TiempoTranscurrido.Add(TimeSpan.FromSeconds(1));

                            }
                            return true;
                        });

                        Encuesta.Office = Cliente.PartnerOffice;
                        Encuesta.Customer = Cliente.Partner;
                        encuesta.QueueID = Cliente.IdTurno;
                    }




                }
            }
        }

        public SampleViewModel Encuesta
        {
            get
            {
                return encuesta;
            }
            set
            {
                if (SetProperty(ref encuesta, value))
                {
                    encuesta = value;
                    OnPropertyChanged();
                }
            }
        }

        #endregion

        #region Process Properties

        internal ScreenStatuses ScreenStatus
        {
            get
            {
                return screenStatus;
            }
            set
            {
                screenStatus = value;
                OnPropertyChanged();
            }
        }

        public string ConnectionUrl
        {
            get
            {
                return BarCodeResult == null
                  ? null
                  : BarCodeResult.Split(new string[] { "/Atencion/Cliente" }, StringSplitOptions.None)[0];
            }
        }

        public string LogoUrl
        {
            get
            {
                return BarCodeResult == null
                    ? null
                    : ConnectionUrl + "/Home/Thumbnail?ImagePath=Logo.png&width=396&height=222";
            }
        }

        public string BarCodeResult
        {
            get
            {
                return barCodeResult;
            }
            set
            {
                try
                {
                    IsBusy = true;
                    var theValue = value;
#if DEBUG
                    theValue = theValue?.Replace("https", "http");
#endif

                    var scanned = value != null && barCodeResult == null;


                    if (SetProperty(ref barCodeResult, theValue))
                    {
                        if (value == null)
                        {
                            Task.Factory.StartNew(() =>
                            {
                                UpdateStatus();
                            });
                        }
                        else if (!Uri.IsWellFormedUriString(value, UriKind.Absolute) || !value.Contains("Cliente/TicketDigital/"))
                        {
                            BarCodeResult = null;
                            MostrarErrorQrCode = true;
                            IsBusy = false;
                        }
                        else
                        {
                            UpdateStatus();
                        }
                    }

                    if (scanned) Resume();


                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }

        public bool IsBusy
        {
            get
            {
                return isBusy;
            }
            set
            {
                if (SetProperty(ref isBusy, value))
                {
                    ReadQRCodeCommand.ChangeCanExecute();
                    SaveSurveyCommand.ChangeCanExecute();
                }


            }
        }

        public string ConnectionID
        {
            get
            {
                return connectionID;
            }
            set
            {
                connectionID = value;
                OnPropertyChanged();
            }
        }

        public bool MostrarBoton
        {
            get
            {
                return ScreenStatus == ScreenStatuses.BarCodeScanner;
            }
        }

        public bool MostrarFormularioEncuesta
        {
            get
            {
                return ScreenStatus == ScreenStatuses.Survey;
            }
        }

        public bool MostrarAgradecimiento
        {
            get
            {
                return ScreenStatus == ScreenStatuses.Finished;
            }
        }

        public bool MostrarServicios
        {
            get
            {
                return ScreenStatus == ScreenStatuses.TicketMonitoring;

            }
        }


        public bool IsEncuestado
        {
            get
            {
                return isEncuestado;
            }
            set
            {
                if (SetProperty(ref isEncuestado, value))
                {

                }

            }
        }

        public bool MostrarErrorQrCode
        {
            get
            {
                return mostrarErrorQrCode;
            }
            set
            {
                if (SetProperty(ref mostrarErrorQrCode, value))
                {

                }
            }
        }

        public bool MostrarErrorConexion
        {
            get
            {
                return mostrarErrorConexion;
            }
            set
            {
                if (SetProperty(ref mostrarErrorConexion, value))
                {

                }
            }
        }


        #endregion

        #region Methods.


        private void initConnection()
        {

                if (barCodeResult != null)
                {

                    if (Device.RuntimePlatform == "Windows")
                    {
                        IsBusy = true;
                        connection = new HubConnection(ConnectionUrl + "/signalr/hubs");

                        AsyncHelpers.RunSync(MonitorTicket);

                        IsBusy = false;


                    }
                    else
                    {
                        IsBusy = true;
                        connection = new HubConnection(ConnectionUrl + "/signalr/hubs");
                        Task.Factory.StartNew(async () =>
                        {
                                                           await MonitorTicket();

                                IsBusy = false;

                        });
                    }


                }
                else
                {
                    if (connection != null)
                        connection.Dispose();


                }

        }

        async Task MonitorTicket()
        {

                Cliente = await this.HttpRequest<ClienteViewModel>(HttpMethod.Get,
                    "/TurnoDetalleApi/DatosTicketImpresion",
                    string.Format("id={0}",
                        BarCodeResult.Split(new string[] { "id=" },
                        StringSplitOptions.None)[1])
                    );

                ticketHub = connection.CreateHubProxy("TicketHub");

                ticketHub.On<bool>("isAlive", (alive) =>
                {


                });

                ticketHub.On<ClienteDetalleViewModel>("update", async (detalle) =>
                {
                    if (detalle.Servicio == null)
                    {
                        try
                        {
                            detalle.Servicio = await this.HttpRequest<string>(HttpMethod.Get, "/ServicioApi/GetNombreServicio", $"IdServicio={detalle.IdServicio}");
                            detalle.SalaEspera = await this.HttpRequest<string>(HttpMethod.Get, "/SalaEsperaApi/GetNombre/", $"id={detalle.IdSalaEspera}");
                        }
                        catch (WebException)
                        {
                            BarCodeResult = null;
                            MostrarErrorConexion = true;
                        }
                    }

                    if (Cliente.Detalles
                        .Where(p => p.IdServicio == detalle.IdServicio)
                        .Any())
                    {
                        var miDetalle = Cliente.Detalles.Last(p => p.IdServicio == detalle.IdServicio);
                        miDetalle.Servicio = detalle.Servicio;
                        miDetalle.SalaEspera = detalle.SalaEspera;
                        miDetalle.Estado = detalle.Estado;
                        miDetalle.TiempoAtencionPromedio = detalle.TiempoAtencionPromedio;
                        miDetalle.TiempoEsperaRestante = detalle.TiempoEsperaRestante;
                        miDetalle.TotalEnCola = detalle.TotalEnCola;
                        miDetalle.TiempoTranscurrido = detalle.TiempoTranscurrido;

                    }
                    else
                    {
                        Device.StartTimer(TimeSpan.FromSeconds(1), () =>
                        {
                            detalle.HasTimer = true;
                            detalle.TiempoTranscurrido = detalle.TiempoTranscurrido.Add(TimeSpan.FromSeconds(1));

                            return true;
                        });
                        Cliente.Detalles.Add(detalle);

                    }
                    UpdateStatus();
                });

                await connection.Start();

                ConnectionID = connection.ConnectionId;


                var sample = await NetworkHelper.HttpRequest<SampleViewModel>("https://sdfghjklfghjkl.com/sadfkljsafdlkjroisdapi/api", HttpMethod.Get, "/survey", $"QueueID={Cliente.IdTurno}&Customer={Cliente.Partner}");
                IsEncuestado = sample != null;

                await ticketHub.Invoke("SetTicket", Cliente.IdTurno);
                await Task.Factory.StartNew(async () =>
                {
                    do
                    {

                        await ticketHub.Invoke("KeepAlive");

                        await Task.Delay(1000 * 60);

                    } while (ScreenStatus == ScreenStatuses.TicketMonitoring);
                });
                IsBusy = false;
                MostrarErrorConexion = false;


        }

        private void UpdateStatus()
        {

                if (BarCodeResult == null)
                {
                    ScreenStatus = ScreenStatuses.BarCodeScanner;
                }
                else if (Cliente != null && Cliente.Detalles.Any(p => new string[] { "EnCola", "Atendiendo", "EsperaCliente" }.Contains(p.Estado)) && !IsEncuestado)
                {
                    OnPropertyChanged(nameof(LogoUrl));

                    ScreenStatus = ScreenStatuses.TicketMonitoring;
                }
                else if (Cliente == null)
                {
                    ScreenStatus = ScreenStatuses.TicketMonitoring;
                }
                else if (!IsEncuestado)
                {
                    ScreenStatus = ScreenStatuses.Survey;
                }
                else
                {
                    ScreenStatus = ScreenStatuses.Finished;
                }

                OnPropertyChanged(nameof(ScreenStatus));
                OnPropertyChanged(nameof(MostrarAgradecimiento));
                OnPropertyChanged(nameof(MostrarBoton));
                OnPropertyChanged(nameof(MostrarFormularioEncuesta));
                OnPropertyChanged(nameof(MostrarServicios));
                IsBusy = false;


        }



        #endregion

        #region Events

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string name = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(storage, value))
                return false;
            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }


        #endregion


    }
公共类TicketDigitalViewModel:INotifyPropertyChanged
{
公共静态TimeSpan服务器ClientTimeDifference{get;set;}
私有布尔mostrarErrorQrCode;
私有静态字符串surveyUri=”https://sdfghjklfghjkl.com/sadfkljsafdlkjroisdapi/api";
私人客户;模型客户;
私人厕所很忙;
私有字符串条码结果;
专用连接;
私人iHubThub;
私有字符串连接ID;
私有屏幕状态屏幕状态;
私有样本视图模型encuesta;
私立学校;
手机条码扫描仪;
bool scannerInitialized=false;
私人住宅;
内部无效恢复()
{
initConnection();
}
公开票证DigitalViewModel()
{
Encuesta=新的SampleViewModel();
ReadQRCodeCommand=新命令(异步()=>
等待ReadQRCode(),
()=>!我很忙);
SaveSurveyCommand=new命令(异步()=>
等待储蓄调查(Encuesta));
CancelSurveyCommand=新命令(异步()=>
等待取消调查(),
()=>!我很忙);
}
公共命令CancelSurveyCommand{get;}
公共命令ReadQRCodeCommand{get;}
公共命令SaveSurveyCommand{get;}
异步任务ReadQRCode()
{
如果(!scannerInitialized)
{
scanner=新的MobileBarcodeScanner();
scannerInitialized=true;
}
条形码结果=空;
var result=wait scanner.Scan();
BarCodeResult=result.Text;
返回结果;
}
#区域数据属性。
公共客户视图模型客户
{
得到
{
回头客;
}
设置
{
SetProperty(参考客户,值);
如果(客户!=null)
{
如果(Device.RuntimePlatform==“Windows”)
{
设备启动计时器(时间跨度从秒开始(1),
() =>
{
foreach(Cliente.Detalles.Where(p=>newstring[]{“EnCola”、“Atendiendo”、“EsperaCliente”}.Contains(p.Estado)))
{
Device.beginInvokeMainThread(()=>