Events 我试图更新Xamarin.Forms中的一个标签,结果它破坏了整个应用程序

Events 我试图更新Xamarin.Forms中的一个标签,结果它破坏了整个应用程序,events,xamarin.forms,label,Events,Xamarin.forms,Label,我的应用程序主页上有一个标签,应该每隔十五秒更新一次,但是它只更新一次,之后,很多事情都停止了。例如,如果我尝试在标签更新后打开一个新页面,页面标题将与“后退”按钮绘制在同一位置(这两个按钮都是由Xamarin在工具栏中生成的),并且页面内容根本不会加载。此外,我在页面上有一个ListView,如果我尝试选择一个项目(应该打开一个新页面),它只在第一次工作,之后ListView消失,但显示在所选项目后面的橙色框保持不变 标签目前的工作原理是,我在App类中有一个计时器,它从我加载到App的OnS

我的应用程序主页上有一个标签,应该每隔十五秒更新一次,但是它只更新一次,之后,很多事情都停止了。例如,如果我尝试在标签更新后打开一个新页面,页面标题将与“后退”按钮绘制在同一位置(这两个按钮都是由Xamarin在工具栏中生成的),并且页面内容根本不会加载。此外,我在页面上有一个ListView,如果我尝试选择一个项目(应该打开一个新页面),它只在第一次工作,之后ListView消失,但显示在所选项目后面的橙色框保持不变

标签目前的工作原理是,我在App类中有一个计时器,它从我加载到App的OnStart()函数(该部分工作正常)的列表中选择一段随机文本,然后触发一个应该更新标签的事件

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Timers;
using System.Reflection;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

using Partylist.Views;
using Partylist.Models;

namespace Partylist
{
    public partial class App : Application, INotifyPropertyChanged
    {
        // Variable to store the currently selected event.
        public static Event selectedEvent;
        // Variable to store the currently selected list.
        public static PartylistList selectedList;
        // Struct to store information about tips.
        public struct Tip
        {
            // A short version of the tip for the banner at the bottom of the screen.
            public string Summary { get; set; }
            // The full tip, which you can read by clicking the "More" button in the banner.
            public string Full { get; set; }
        }
        // Array of tips.
        public List<Tip> tips = new List<Tip>();
        // Current tip.
        public Tip CurrentTip { get; set; }
        // Timer that gets the tip to update.
        public Timer tipTimer = new Timer(15000);
        // Random number generator for choosing the tip.
        public Random rand = new Random();
        // Event that tells the tip banners on the pages to update.
        public static event EventHandler TipUpdate;

        // Constructor.
        public App()
        {
            // Do whatever initialization stuff this does.
            InitializeComponent();

            // Subscribes the timer's event handling function to its event.
            tipTimer.Elapsed += OnTimerElapsed;

            // Open the first page: the list of events.
            MainPage = new NavigationPage(new EventsPage()) {
                BarTextColor = Color.FromHex("FF4081")
            };
        }

        // Loads tips data.
        private void LoadTips()
        {
            // Variable for the assembly.
            var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
            // Variable for the stream I use to read the text file.
            Stream tipsStream = assembly.GetManifestResourceStream("Partylist.Resources.tips.txt");
            // And a variable for the StreamReader.
            StreamReader tipsReader = new StreamReader(tipsStream);
            // Read the whole file into the list of tips.
            while (!tipsReader.EndOfStream)
            {
                // Read a line into a "sumamry" variable.
                string sum = tipsReader.ReadLine();
                // Read another line into a "full" variable.
                string full = tipsReader.ReadLine();
                // Add an item to the list of tips that uses "summary" as the summary 
                // and "full" as the full tip.
                tips.Add(new Tip()
                {
                    Summary = sum,
                    Full = full
                });
            }
            // Random index of the chosen tip.
            int index = rand.Next(tips.Count);
            // Set the current tip as the tip at that index.
            CurrentTip = tips.ElementAt(index);
            // Start timer (if it needs it).
            tipTimer.Start();
        }

        // Event handling function for when the timer goes off.
        private void OnTimerElapsed(object source, ElapsedEventArgs e)
        {
            // Random index of the chosen tip.
            int index = rand.Next(tips.Count);
            // Set the current tip as the tip at that index.
            CurrentTip = tips.ElementAt(index);
            // Fire the event to update the pages' tip banners.
            TipUpdate?.Invoke(this, e);
        }

        // Standard lifecycle events.
        protected override void OnStart()
        {
            // Call a function that loads the tips.
            LoadTips();
        }

        protected override void OnSleep()
        {
        }

        protected override void OnResume()
        {
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.IO;
使用System.Linq;
使用系统计时器;
运用系统反思;
使用Xamarin.Forms;
使用Xamarin.Forms.Xaml;
使用Partylist.Views;
使用Partylist.Models;
名称空间Partylist
{
公共部分类应用程序:应用程序,INotifyPropertyChanged
{
//变量来存储当前选定的事件。
公共静态事件选择事件;
//变量来存储当前选定的列表。
公共静态PartyList selectedList;
//结构来存储有关提示的信息。
公共结构提示
{
//屏幕底部横幅提示的简短版本。
公共字符串摘要{get;set;}
//完整提示,您可以通过单击横幅中的“更多”按钮来阅读。
公共字符串已满{get;set;}
}
//一系列提示。
公共列表提示=新列表();
//当前提示。
公共提示CurrentTip{get;set;}
//获取要更新的提示的计时器。
公共定时器tipTimer=新定时器(15000);
//用于选择尖端的随机数生成器。
公共随机兰德=新随机();
//事件,通知页面上的提示横幅进行更新。
公共静态事件EventHandler TipUpdate;
//构造器。
公共应用程序()
{
//做任何初始化的事情。
初始化组件();
//将计时器的事件处理函数订阅到其事件。
tipTimer.Appeased+=OnTimeRecursed;
//打开第一页:事件列表。
MainPage=新导航页面(新事件页面()){
BarTextColor=Color.FromHex(“FF4081”)
};
}
//加载提示数据。
私有void加载提示()
{
//程序集的变量。
var assembly=IntrospectionExtensions.GetTypeInfo(typeof(App)).assembly;
//用于读取文本文件的流的变量。
Stream tipsStream=assembly.GetManifestResourceStream(“Partylist.Resources.tips.txt”);
//和StreamReader的一个变量。
StreamReader tipsReader=新StreamReader(tipsStream);
//将整个文件读入提示列表。
而(!tipsReader.EndOfStream)
{
//将一行读入“sumamry”变量。
string sum=tipsReader.ReadLine();
//将另一行读入“full”变量。
string full=tipsReader.ReadLine();
//向使用“摘要”作为摘要的提示列表中添加一项
//“完整”作为完整提示。
添加(新提示()
{
汇总=总和,
满的
});
}
//所选尖端的随机索引。
int index=rand.Next(tips.Count);
//将当前提示设置为该索引处的提示。
CurrentTip=tips.ElementAt(索引);
//启动计时器(如果需要)。
tipTimer.Start();
}
//计时器关闭时的事件处理功能。
私有void onTimeRecursed(对象源,ElapsedEventArgs e)
{
//所选尖端的随机索引。
int index=rand.Next(tips.Count);
//将当前提示设置为该索引处的提示。
CurrentTip=tips.ElementAt(索引);
//触发事件以更新页面的提示横幅。
TipUpdate?调用(此,e);
}
//标准生命周期事件。
受保护的覆盖void OnStart()
{
//调用加载提示的函数。
加载提示();
}
受保护的覆盖void OnSleep()
{
}
受保护的覆盖void OnResume()
{
}
}
}
在页面的OnAppearing()方法中,我将标签的文本设置为当前提示(此时为null),并订阅函数,将其更新为计时器触发的事件

using Partylist.Models;

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Partylist.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class EventsPage : ContentPage
    {
        // Text of the tip banner.
        public string BannerText { get; set; }

        // List of events, used to populate 
        // the page's ListView (see the XAML).
        public ObservableCollection<Event> EventList { get; set; }

        // Constructor.
        public EventsPage()
        {
            // Does all the stuff to make the page
            // exist that doesn't involve anything 
            // specific to this particular page in
            // this particular app.
            InitializeComponent();
            // Set the label's BindingContext to the 
            // App class so it can update its text.
            tipLabel.BindingContext = (App)App.Current;
        }

        // Runs when the page appears.
        protected override void OnAppearing()
        {
            // Call the regular OnAppearing method.
            base.OnAppearing();

            // Set the BindingContext of the page to itself.
            BindingContext = this;

            // Update the ListView.
            UpdateListView();

            // Set the banner's text to the current tip's sumamry.
            tipLabel.Text = ((App)App.Current).CurrentTip.Summary;
            OnPropertyChanged("CurrentTip");

            // Subscribe the OnTipUpdate function to the tipUpdate event in the app
            // class.
            App.TipUpdate += OnTipUpdate;
        }

        // Function to update the ListView whent he page loads or when something changes.
        private void UpdateListView()
        {
            // Set the EventList to a new ObservableCollection
            // which will be populated.
            EventList = new ObservableCollection<Event>();

            // Loop to populate the ObservableCollection.
            for (int i = 0; i < Directory.GetDirectories(
                Environment.GetFolderPath(
                    Environment.SpecialFolder
                    .LocalApplicationData))
                .Length; i++)
            {
                // Add a new event.
                EventList.Add(new Event()
                {
                    // Set the folder name to the name of the folder 
                    // that the even corresponds to.
                    FolderName = new DirectoryInfo(Directory.GetDirectories(
                    Environment.GetFolderPath(
                        Environment.SpecialFolder
                        .LocalApplicationData))[i]).Name,
                    // Sets the date/time created to the folder's
                    // creation date.
                    DateCreated = Directory
                    .GetCreationTime(Directory.GetDirectories(
                    Environment.GetFolderPath(
                        Environment.SpecialFolder
                        .LocalApplicationData))[i]),
                    // Sets the date/time last edited to the 
                    // folder's write date.
                    DateEdited = Directory
                    .GetLastWriteTime(Directory.GetDirectories(
                    Environment.GetFolderPath(
                        Environment.SpecialFolder
                        .LocalApplicationData))[i])
                });
                // Set the ItemsSource of the ListView in the 
                // XAML to the ObservableCollection.
                EventsListView.ItemsSource = EventList;
                // Calls OnPropertyChanged() which makes the ListView update.
                OnPropertyChanged("EventList");
            }
        }

        // Function to go to the "New Event" page.
        async void OnNewEventClicked(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new NewEventPage());
        }

        // Function for when a ListView item is selected.
        async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            App.selectedEvent = (Event)e.SelectedItem;
            await Navigation.PushAsync(new ListsPage());
        }

        // Function to delete an event if the "Delete" context action is selected.
        async void OnDelete(object sender, EventArgs e)
        {
            // Represents the thing to be deleted.
            var del = (MenuItem)sender;
            // Displays a confirmnation popup and stores the user's answer in a variable.
            var answer = await DisplayAlert("Delete this event?", 
                "Are you sure you want to delete the event: \"" + 
                ((Event)del.CommandParameter).FolderName + "\"?", "Delete", "Cancel");
            // If the user accepted, delete the event with the MenuItem that ran this function.
            if (answer)
            {
                Directory.Delete(Path.Combine(Environment.GetFolderPath(
                    Environment.SpecialFolder.LocalApplicationData), 
                    ((Event)del.CommandParameter).FolderName), true);
                // Set the ItemsSource to null and back to make the ListView update.
                EventsListView.ItemsSource = null;
                UpdateListView();
            }
        }

        // Function for when the current tip updates.
        public void OnTipUpdate(object sender, EventArgs e)
        {
            // Make the label's text update.
            tipLabel.Text = ((App)App.Current).CurrentTip.Summary;
            OnPropertyChanged("CurrentTip");
        }
    }
}
使用Partylist.Models;
使用制度;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用系统组件模型;
使用System.IO;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用Xamarin.Forms;
使用Xamarin.Forms.Xaml;
名称空间Partylist.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
公共部分类事件页面:ContentPage
{
//提示横幅的文本。
公共字符串BannerText{get;set;}
//事件列表,用于填充
//页面的列表视图(参见XAML)。
公共ObservableCollection事件列表{get;set;}
//构造器。
公共活动
{
//做所有的事情,使网页
//不存在的存在
<?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"
             mc:Ignorable="d"
             x:Class="Partylist.Views.EventsPage"
             Title="Events"
             BackgroundColor="White">
    <ContentPage.ToolbarItems>
        <ToolbarItem IconImageSource="settings_gear.png"
                     Priority="0"/>
    </ContentPage.ToolbarItems>

    <ContentPage.Content>
        <!--Main layout of the page-->
        <StackLayout>
            <!--ListView of the events-->
            <ListView x:Name="EventsListView"
                      ItemSelected="OnItemSelected">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <!--These contewxt actions are buttons that appear
                            when you long press the item (Android) or swipe 
                            left (iOS).-->
                            <ViewCell.ContextActions>
                                <MenuItem Clicked="OnDelete"
                                          CommandParameter="{Binding .}"
                                          Text="Delete"
                                          IsDestructive="true"/>
                            </ViewCell.ContextActions>
                            <!--This is the content that actually appears-->
                            <StackLayout Padding="20,5">
                                <Label Text="{Binding FolderName}"
                                       TextColor="#FF7700"
                                       FontSize="Large"/>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

            <!--"New Event" button-->
            <Button Text="+ Add New Event"
                    TextColor="#ff418b"
                    FontSize="Large"
                    BackgroundColor="#00ffffff"
                    Clicked="OnNewEventClicked"/>

            <!--The banner at the bottom of the screen that gives tips-->
            <Frame BorderColor="#ff418b"
                   Padding="0">
                <FlexLayout Direction="Row"
                            AlignItems="Stretch"
                            JustifyContent="SpaceBetween">
                    <!--The "Tip" icon-->
                    <Image Source="tip_icon.png"
                           Margin="10"
                           FlexLayout.Basis="50"/>
                    <!--The short version of the tip-->
                    <Label x:Name="tipLabel"
                           VerticalTextAlignment="Center"
                           TextColor="#bb0099"
                           FontSize="Medium"
                           FontAttributes="Bold"
                           FlexLayout.Basis="250"/>
                    <!--The button that opens up a screen 
                    with tyhe rest of the tip-->
                    <Button Text="More"
                            TextColor="White"
                            FontAttributes="Bold"
                            FontSize="Medium"
                            BackgroundColor="#ff418b"
                            FlexLayout.Basis="100"/>
                </FlexLayout>
            </Frame>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
Device.BeginInvokeOnMainThread (() => {
  label.Text = "Async operation completed";
});