Я написал программу, которую можно использовать для выключения (выключения, перезапуска, спящего режима, приостановки) ПК через некоторое время, в определенное время или ежедневно в определенное время.
Когда я запускаюВ приложении в первый раз все (включая вид) работает нормально.Но когда ПК возобновляет работу после приостановки / спящего режима, пользовательский интерфейс, похоже, больше не отвечает.
У меня есть базовая модель:
class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
private bool _runCountdown;
public bool RunCountdown
{
get { return _runCountdown; }
set
{
_runCountdown = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(RunCountdown)));
if (RunCountdown)
{
TimeRemainingVisibility = Visibility.Visible;
}
else
{
TimeRemainingVisibility = Visibility.Hidden;
}
}
}
private Visibility _timeRemainingVisibility;
public Visibility TimeRemainingVisibility
{
get { return _timeRemainingVisibility; }
set
{
_timeRemainingVisibility = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(TimeRemainingVisibility)));
}
}
//...
}
, к которой пользовательский интерфейс привязан:
<Grid>
<StackPanel Orientation="Vertical" Margin="0,0">
<Grid Margin=" 4,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Margin="16,0,0,0">Shutdown mode:</Label>
<ComboBox Grid.Column="1" Name="CB_Mode" HorizontalAlignment="Left" VerticalAlignment="Center" Width="160" SelectedItem="{Binding ShutdownMode}" ToolTip="{Binding Shutdowndescription}"/>
</Grid>
<Expander Header="Shutdown timer:" IsExpanded="True">
<Grid Margin=" 4,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="1" Margin="0,2" StrokeThickness="2" Stroke="Gray" Width="160" HorizontalAlignment="Left"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" Margin="5">
<TextBox Style="{StaticResource TimeTextBox}" Text="{Binding Path=Timer[0]}"/>
<Label Style="{StaticResource TimeLabel}">h</Label>
<TextBox Style="{StaticResource TimeTextBox}" Text="{Binding Path=Timer[1]}"/>
<Label Style="{StaticResource TimeLabel}">min</Label>
<TextBox Style="{StaticResource TimeTextBox}" Text="{Binding Path=Timer[2]}"/>
<Label Style="{StaticResource TimeLabel}">sec</Label>
</StackPanel>
<Button Grid.Column="2" Name="B_StartTimer" Click="ButtonStart_Click" Style="{StaticResource GreenButton}">Start</Button>
</Grid>
</Expander>
<Expander Header="Shutdown time:" IsExpanded="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="4,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<DatePicker Grid.Column="1" Name="DP_ShutdownDate" SelectedDate="{Binding ShutdownDate}" Margin="0" Visibility="{Binding DateVisibility}"/>
<CheckBox Grid.Column="2" Name="CB_ShutdownDayly" Content="dayly" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding Dayly}"/>
</Grid>
<Grid Grid.Row="1" Margin="4,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="1" Margin="0,2" StrokeThickness="2" Stroke="Gray" Width="160" HorizontalAlignment="Left"></Rectangle>
<StackPanel Grid.Column="1" Orientation="Horizontal" Margin="5">
<TextBox Style="{StaticResource TimeTextBox}" Text="{Binding Path=Date[0]}"/>
<Label Style="{StaticResource TimeLabel}">h</Label>
<TextBox Style="{StaticResource TimeTextBox}" Text="{Binding Path=Date[1]}"/>
<Label Style="{StaticResource TimeLabel}">min</Label>
<TextBox Style="{StaticResource TimeTextBox}" Text="{Binding Path=Date[2]}"/>
<Label Style="{StaticResource TimeLabel}">sec</Label>
</StackPanel>
<Button Grid.Column="2" Click="ButtonStart_Click" Style="{StaticResource GreenButton}">Start</Button>
</Grid>
</Grid>
</Expander>
<Grid Margin=" 4,2" Visibility="{Binding TimeRemainingVisibility}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Margin="16,0,0,0">Time Remaining:</Label>
<StackPanel Orientation="Vertical" Grid.Column="1" ClipToBounds="True" Margin="0,5,0,0">
<TextBox Text="{Binding Path=TimeToShutdown, StringFormat=HH:mm:ss}" ClipToBounds="True" VerticalContentAlignment="Center" Padding="5,0" BorderThickness="0"/>
<TextBox Text="{Binding Path=DisplayOnlyShutdownDate, StringFormat=yyyy-MM-dd HH:mm:ss}" ClipToBounds="True" VerticalContentAlignment="Center" Padding="5,0" BorderThickness="0"/>
</StackPanel>
<Button Grid.Column="2" Click="ButtonStop_Click" IsCancel="True" Style="{StaticResource RedButton}">Stop</Button>
</Grid>
</StackPanel>
</Grid>
Последняя сетка содержит соответствующую информацию.Стили содержат только информацию о стиле, никаких поведений, команд и т. Д.
В своем коде я установил для ViewModels RunCountdown значение true или false:
private void OnPowerChange(object s, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Resume:
_vm = XmlHelper.ReadConfig(CONFIGPATH);
if (_vm.Dayly)
{
ButtonStart_Click(new Button(), null);
if (!ni.Visible)
{
ni.Visible = true;
}
}
break;
//case PowerModes.Suspend:
// ni.Visible = false;
// break;
default: break;
}
}
private void ButtonStart_Click(object sender, RoutedEventArgs e)
{
Button startButton = (Button)sender;
if (!_vm.RunCountdown)
{
SetShutdownTime(startButton);
}
else
{
if (MessageBox.Show("Ein Shutdown Timer läuft bereits.\r\nWollen sie wirklich einen neuen starten?",
"Timer läuft bereits", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.Yes) == MessageBoxResult.Yes)
{
_vm.RunCountdown = false;
Thread.Sleep(1000);
SetShutdownTime(startButton);
}
}
}
private void SetShutdownTime(Button startButton)
{
_vm.DisplayOnlyShutdownDate = DateTime.Now;
if (startButton.Name == "B_StartTimer")
{
_vm.DisplayOnlyShutdownDate = _vm.DisplayOnlyShutdownDate.AddHours(Convert.ToDouble(_vm.Timer[0]))
.AddMinutes(Convert.ToDouble(_vm.Timer[1]))
.AddSeconds(Convert.ToDouble(_vm.Timer[2]));
}
else
{
if (!_vm.Dayly)
{
_vm.DisplayOnlyShutdownDate = _vm.ShutdownDate;
}
else
{
_vm.DisplayOnlyShutdownDate = DateTime.Now.Date;
}
_vm.DisplayOnlyShutdownDate = _vm.DisplayOnlyShutdownDate.Date.AddHours(Convert.ToDouble(_vm.Date[0]))
.AddMinutes(Convert.ToDouble(_vm.Date[1]))
.AddSeconds(Convert.ToDouble(_vm.Date[2]));
while (_vm.DisplayOnlyShutdownDate < DateTime.Now)
{
_vm.DisplayOnlyShutdownDate = _vm.DisplayOnlyShutdownDate.AddDays(1);
}
}
//secondsTimer.Start();
StartCountdown();
}
private void StartCountdown()
{
_vm.RunCountdown = true;
Task.Run(() =>
{
while (_vm.DisplayOnlyShutdownDate > DateTime.Now && _vm.RunCountdown)
{
_vm.TimeToShutdown = DateTime.Today + (_vm.DisplayOnlyShutdownDate - DateTime.Now);
ni.Text = $"Time until {Enum.GetName(typeof(WindowsShutdownMode), _vm.ShutdownMode)}: {_vm.TimeToShutdown.ToString("HH:mm:ss")}";
int remaining = Convert.ToInt32((_vm.DisplayOnlyShutdownDate - DateTime.Now).TotalSeconds);
if (remaining == 300)
{
Task.Run(() =>
{
MessageBox.Show($"5 min remaining");
});
}
Thread.Sleep(1000);
}
if (_vm.RunCountdown)
{
InitiateShutdown();
}
}
);
}
private void InitiateShutdown()
{
_vm.RunCountdown = false;
//ButtonStop_Click(null, null);
XmlHelper.SaveConfig(_vm, CONFIGPATH);
switch (_vm.ShutdownMode)
{
case WindowsShutdownMode.Shutdown: System.Diagnostics.Process.Start("shutdown", "/s /t 0"); break;
case WindowsShutdownMode.Restart: System.Diagnostics.Process.Start("shutdown", "/r /t 0"); break;
case WindowsShutdownMode.Hibernate: System.Windows.Forms.Application.SetSuspendState(System.Windows.Forms.PowerState.Hibernate, false, false); break;
case WindowsShutdownMode.Suspend: System.Windows.Forms.Application.SetSuspendState(System.Windows.Forms.PowerState.Suspend, false, false); break;
default: break;
}
}
Как упоминалось ранее, пользовательский интерфейс работаетхорошо, когда я изначально запускаю программу.При нажатии на одну из кнопок запуска появляется Сетка, которая имеет Visibility = "{Binding TimeRemainingVisibility} , при нажатии кнопки остановки она исчезает. Я могу делать это бесчисленное количество раз, когда она работает нормально. Однако, когда отсчет времениПосле завершения система завершает работу, и я снова запускаю ее. Пользовательский интерфейс, в частности упомянутая Grid, больше не меняется.
Когда я устанавливаю точки останова в моей модели представления, я даже могу видеть изменения, происходящие со свойствами послеsupend-resume, но Grid остается невидимым. При повторном нажатии на таймеры запуска Grid также должен отображаться - это не так.
Имеет ли это какое-либо отношение к «экрану входа в Windows», которыйотображается после возобновления работы? Как я могу заставить это работать так, как должно?Еще один вопрос, который на самом деле не меняет функциональность: лучше ли намe System.Timer для обновления времени, отображаемого в пользовательском интерфейсе каждую секунду, или для использования цикла while с Thread.Sleep (1000) и почему?
Заранее спасибо за помощь.