Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# windows phone应用程序中截至日期的倒计时_C#_Wpf_Xaml_Windows Phone 8_Countdown - Fatal编程技术网

C# windows phone应用程序中截至日期的倒计时

C# windows phone应用程序中截至日期的倒计时,c#,wpf,xaml,windows-phone-8,countdown,C#,Wpf,Xaml,Windows Phone 8,Countdown,我正在创建一个特定日期的倒计时。剩余天数、剩余小时和剩余分钟必须显示在文本块中 用XAML做了一个平面设计,知道如何计算时间跨度。现在我需要一个实时更新程序,而应用程序正在运行 我的Xaml <Grid x:Name="myLayoutGrid" Background="CadetBlue" Margin="0,-26.667,0,-0.333" > <TextBlock x:Name="countDays" H

我正在创建一个特定日期的倒计时。剩余天数、剩余小时和剩余分钟必须显示在文本块中

用XAML做了一个平面设计,知道如何计算时间跨度。现在我需要一个实时更新程序,而应用程序正在运行

我的Xaml

<Grid x:Name="myLayoutGrid"
      Background="CadetBlue" Margin="0,-26.667,0,-0.333"
      >

    <TextBlock x:Name="countDays" 
               HorizontalAlignment="Left" 
               Margin="45,150,0,0" 
               TextWrapping="Wrap" 
               Text="Dagen" 
               VerticalAlignment="Top"
               FontFamily="Tahoma"
               FontSize="34" Loaded="countDays_Loaded"/>
    <TextBlock x:Name="countHours" 
               HorizontalAlignment="Left" 
               Margin="45,200,0,0" 
               TextWrapping="Wrap" 
               Text="Uur" 
               VerticalAlignment="Top" 
               FontFamily="Tahoma"
               FontSize="30" Loaded="countHours_Loaded"/>
    <TextBlock x:Name="countMinutes" 
               HorizontalAlignment="Left"
               Margin="45,250,0,0" 
               TextWrapping="Wrap" 
               Text="Minuten" 
               VerticalAlignment="Top"
               FontFamily="Tahoma"
               FontSize="26" Loaded="countMinutes_Loaded"/>
在我理解了代码以及为什么要使用该代码之后,我想清理我的代码(将计时器放入类中)。之后,我学习了HUB应用程序,我将在binding元素中使用它


任何帮助都很好。

您需要某种计时器来定期刷新剩余时间。尝试以下方法:

public partial class MainWindow : Window
{
    private readonly DateTime _endDate;
    private readonly DispatcherTimer _timer;

    public MainWindow()
    {
        InitializeComponent();

        _endDate = new DateTime(2016, 1, 1, 15, 0, 0);
        _timer = new DispatcherTimer();
        _timer.Tick += CountDown;
        _timer.Interval = TimeSpan.FromMinutes(1);
        _timer.Start();
    }

    private void CountDown(object sender, EventArgs e)
    {
        var remainingTime = _endDate.Subtract(DateTime.Now);

        countDays.Text = string.Format("{0} Dagen", remainingTime.Days);
        countHours.Text = string.Format("{0} Uur", remainingTime.Hours);
        countMinutes.Text = string.Format("{0} Minuten", remainingTime.Minutes);
    }
}
要使代码编译,请从XAML中的文本块中删除
load=“countX\u-Loaded”
EventHandler

<Window x:Class="Stackoverflow28009341.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="myLayoutGrid" Background="CadetBlue" Margin="0,-26.667,0,-0.333">
        <TextBlock x:Name="countDays" 
               HorizontalAlignment="Left" 
               Margin="45,150,0,0" 
               TextWrapping="Wrap" 
               Text="Dagen" 
               VerticalAlignment="Top"
               FontFamily="Tahoma"
               FontSize="34"/>
        <TextBlock x:Name="countHours" 
               HorizontalAlignment="Left" 
               Margin="45,200,0,0" 
               TextWrapping="Wrap" 
               Text="Uur" 
               VerticalAlignment="Top" 
               FontFamily="Tahoma"
               FontSize="30"/>
        <TextBlock x:Name="countMinutes" 
               HorizontalAlignment="Left"
               Margin="45,250,0,0" 
               TextWrapping="Wrap" 
               Text="Minuten" 
               VerticalAlignment="Top"
               FontFamily="Tahoma"
               FontSize="26"/>
    </Grid>
</Window>

当您使用C#/XAML为WP8开发应用程序时,应该使用MVVM模式

这意味着您要创建一个
视图
(例如XAML窗口),然后为其数据创建一个单独的上下文,名为
ViewModel
。当数据发生更改时,您需要通过实现
INotifyPropertyChanged
接口通知视图更改

要进行定期更改,应该使用基于任务的异步模式。这样您的UI线程就不会被阻塞。使用
任务
最容易做到这一点

当然,还有其他几种方法可以做到这一点,但这是我的建议

然后,您的应用程序可以如下所示

main window.xaml

<!-- This would be <phone:PhoneApplicationPage in WP8 app -->
<!-- e.g. phone:PhoneApplicationPage x:Class="PhoneApp1.MainPage"-->
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1"
        Title="MainWindow"
        Height="116"
        Width="250">
    <Window.DataContext>
        <wpfApplication1:MainViewModel />
    </Window.DataContext>

    <StackPanel VerticalAlignment="Center">
        <!-- Bind displayed text to MainViewModel's CountDown property -->
        <!-- This way it automically updates the TextBlock whenever value is changed -->
        <TextBlock Text="{Binding CountDown}" FontSize="24" TextAlignment="Center" />
    </StackPanel>        
</Window>
MainViewModel.cs

// No code added here, this is the initial class structure.
// This needs to be in same namespace as MainWindow/Page XAML (partial)
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}
// This would be plain C# class in WP8, too
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace WpfApplication1
{
    public class MainViewModel : INotifyPropertyChanged
    {
        // This event takes care of notifying the page so it updates
        public event PropertyChangedEventHandler PropertyChanged;
        private string _countDown;

        public MainViewModel()
        {
            // Day to countdown to
            DateTime targetDate = DateTime.Now.AddDays(5d);

            // Start new thread
            Task.Factory.StartNew(() =>
                {
                    // Loop until target date and update value every second
                    while (DateTime.Now <= targetDate)
                    {
                        // Format and set new value
                        CountDown = (targetDate - DateTime.Now).ToString("d'd 'h'h 'm'm 's's'");
                        Thread.Sleep(1000);
                    }
                    // Final value
                    CountDown = "It's tiem!";
                });
        }

        // Value displayed in Page's TextBlock
        public string CountDown
        {
            get { return _countDown; }
            set { _countDown = value; OnPropertyChanged();}
        }

        // This is INotifyPropertyChanged implementation
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) 
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

如果您不熟悉WP开发、关注点分离和设计模式,codebehind中的计时器可能是最简单、最快和最简单的实现。仍然有人应该努力远离代码背后的开发。@Mikko这是真的。在这方面,你的方法肯定是更具前景的。@khlr。嗯,我试过这么做,但没能成功。我现在更喜欢这个简单的选择。因为我是从编码开始的。这个代码我也能读。也许我应该公开字符串,以便将其绑定到文本块。(我承认Mikko的解决方案更强,但我的知识还不太好。)@Tezzo什么还不起作用?到目前为止,你不需要任何公众成员。是的,Mikko的方法更先进,你可以尝试“升级”以后再看。@khlr它不会出现在我的应用程序中。我理解你使用的逻辑。我删除了加载的事件。我最好只使用文本块构建一个新的XAMl。不知怎么的,它不会出现。也许这是最好的实现,但我的知识不足以解决这个问题。我是从“空白应用程序”构建的在visual studio中。示例已完成,您可以根据自己的需要对其进行修改。我很感谢。但我不知道如何实现,因为我正在学习。我很好,这没有意义。我刚开始使用一个空白应用程序,一个文本块。完整的代码在那里。我可以添加注释,但其他方面……您必须管理或获得新的答案。我同意。我确定当我进一步掌握winphone 8 XAML和C#之后,我会继续使用你的解决方案。提前感谢。我同意最好在其他地方使用rocketscience,使用XAML只显示数据。你不应该大量编辑初始问题,因为它会断章取义,对其他任何人都没有好处。打开一个新的埃斯蒂恩完全没问题。
// This would be plain C# class in WP8, too
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace WpfApplication1
{
    public class MainViewModel : INotifyPropertyChanged
    {
        // This event takes care of notifying the page so it updates
        public event PropertyChangedEventHandler PropertyChanged;
        private string _countDown;

        public MainViewModel()
        {
            // Day to countdown to
            DateTime targetDate = DateTime.Now.AddDays(5d);

            // Start new thread
            Task.Factory.StartNew(() =>
                {
                    // Loop until target date and update value every second
                    while (DateTime.Now <= targetDate)
                    {
                        // Format and set new value
                        CountDown = (targetDate - DateTime.Now).ToString("d'd 'h'h 'm'm 's's'");
                        Thread.Sleep(1000);
                    }
                    // Final value
                    CountDown = "It's tiem!";
                });
        }

        // Value displayed in Page's TextBlock
        public string CountDown
        {
            get { return _countDown; }
            set { _countDown = value; OnPropertyChanged();}
        }

        // This is INotifyPropertyChanged implementation
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) 
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
timer.Tick += (sender, args) =>
    {
        DateTime now = DateTime.Now;
        int difference = (int) (targetDate - now).TotalSeconds;
        CountDown = difference >= 0 ? 
                    (targetDate - now).ToString("d'd 'h'h 'm'm 's's'") : 
                    "It's tiem!";
        if (difference < 0)
            timer.Stop();
    };
timer.Start();