06.12.2022, 08:36. Показов 1874. Ответов 26
Добрый день, форумчане, знатоки WPV, MVVM! Снова прошу помощи)

Работаю над проектом, что-то вроде будильника(напоминания). По истечению времени, указанного пользователем, должно открываться небольшое окно с напоминаниями.
У меня есть основное окно, где в DataGrid отображаются сохраненные напоминания.
Есть окно, которое должно быть "всплывающим" при срабатывании таймера, и в которое должны передаваться данные из объекта, сохраненного в коллекции. И есть команда открытия "всплывающего окна".
На данный момент "всплывающее окно" привязано к кнопке в меню MainWindow. А вот как открыть это окно по истечении времени (не нажимая на кнопку) не представляю. Для таймера пока что есть только метод, который возвращает время в минутах.
Подскажите, возможно ли и как можно реализовать такую задачу?
Код главного окна:
| XML |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
| <Window x:Class="Memory_Refresher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Memory_Refresher"
xmlns:cmd="clr-namespace:Memory_Refresher.Commands"
xmlns:vm="clr-namespace:Memory_Refresher.ViewModels"
xmlns:serv="clr-namespace:Memory_Refresher.Services"
Title="{Binding Tittle}" MinHeight="500" MinWidth="800" Height="800" Width="1200"
WindowStartupLocation="CenterScreen" Icon="/Views/Windows/MemoryRefresher.png">
<Window.DataContext>
<vm:MainWindow_VM/>
</Window.DataContext>
<Window.InputBindings>
<KeyBinding Command="{Binding SaveRemindersCmd}" Key="S" Modifiers="Ctrl"/>
</Window.InputBindings>
<DockPanel>
<StackPanel DockPanel.Dock="Top">
<TextBlock FontSize="45"
Text="Memory Refresher++"
TextWrapping="Wrap"
TextAlignment="Left"
VerticalAlignment="Center"
FontFamily="Algerian"
FontWeight="Normal" FontStyle="Normal">
<TextBlock.Foreground>
<LinearGradientBrush>
<GradientStop Color="GreenYellow" Offset="0.1"/>
<GradientStop Color="Yellow" Offset="0.2"/>
<GradientStop Color="Red" Offset="1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
<TextBlock.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,9">
<GradientStop Color="LimeGreen" Offset="0.85"/>
<GradientStop Color="Blue" Offset="0.75"/>
<GradientStop Color="Red" Offset="0.65"/>
<GradientStop Color="Yellow" Offset="0.5"/>
<GradientStop Color="Black" Offset="0.4"/>
</LinearGradientBrush>
</TextBlock.Background>
</TextBlock>
</StackPanel>
<Menu DockPanel.Dock="Top"
Style="{StaticResource MenuCustomStyle}">
<MenuItem Header="Файл">
<MenuItem Header="Новое напоминание"
Style="{StaticResource MenuItemStyle}">
<MenuItem.Command>
<cmd:AddNewReminderCommand/>
</MenuItem.Command>
</MenuItem>
<MenuItem Header="Сохранить все напоминания Ctrl+S"
Style="{StaticResource MenuItemStyle}"
Command="{Binding SaveRemindersCmd}"/>
<MenuItem Header="Сохранить и выйти"
Style="{StaticResource MenuItemStyle}"
Command="{Binding CloseApp}"/>
</MenuItem>
<MenuItem Header="Помощь"
Style="{StaticResource MenuItemStyle}"/>
<MenuItem Header="Окно будильника"
Style="{StaticResource MenuItemStyle}">
<MenuItem.Command>
<cmd:OpenAlarmWindowCommand/>
</MenuItem.Command>
</MenuItem>
</Menu>
<TabControl DockPanel.Dock="Bottom"
Style="{StaticResource TabControlStyle}">
<TabItem Header="Напоминания" FontSize="14"
Style="{StaticResource TabItemCustomStyle}">
<DockPanel>
<StackPanel x:Name="Buttons"
DockPanel.Dock="Top"
VerticalAlignment="Top"
Orientation="Horizontal"
Height="40">
<Button Content="Новое напоминание"
Width="200"
Margin="5"
Height="30"
HorizontalAlignment="Left"
Style="{StaticResource CheckButtonStyle}">
<Button.Command>
<cmd:AddNewReminderCommand/>
</Button.Command>
</Button>
<Button Content="Сохранить"
Width="200"
Margin="5"
Height="30"
HorizontalAlignment="Left"
Style="{StaticResource SaveButtonStyle}"
Command="{Binding SaveRemindersCmd}">
</Button>
<Button Content="Удалить напоминание"
Width="200"
Margin="5"
Height="30"
HorizontalAlignment="Left"
Style="{StaticResource RemoveButtonStyle}"
Command="{Binding ReminderDeleteCmd}">
</Button>
<StackPanel.Background>
<LinearGradientBrush >
<GradientStop Color="#FFEAEAEA" Offset="1.5"/>
<GradientStop Color="#FFBDF3F3" Offset="1.3"/>
<GradientStop Color="#FFC9EDED" Offset="1"/>
<GradientStop Color="#FFD5EFFF" Offset="0.5"/>
</LinearGradientBrush>
</StackPanel.Background>
</StackPanel>
<DataGrid AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
IsReadOnly="True"
Background="LightGray"
ItemsSource ="{Binding Source={x:Static serv:Collections.Reminders}}"
SelectedItem="{Binding SelectedReminder}">
<DataGrid.InputBindings>
<KeyBinding Key="Delete" Command="{Binding ReminderDeleteCmd}"/>
</DataGrid.InputBindings>
<DataGrid.Columns>
<DataGridTextColumn Header="Index"
Width="75"
Binding="{Binding IndexReminder}"/>
<DataGridTextColumn Header="Заголовок"
Width="250"
Binding="{Binding TittleReminder}"/>
<DataGridTextColumn Header="Текст"
Width="*"
Binding="{Binding MessageReminder}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Время напоминания"
Width="200"
Binding="{Binding DateTimeReminder, StringFormat={}{0:HH:mm}}" />
<DataGridTextColumn Header="Дата напоминания"
Width="200"
Binding="{Binding DateTimeReminder, StringFormat={}{0:dd.MM.yyyy}}"/>
</DataGrid.Columns>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Выполнено"
Command="{Binding ReminderCompletedCmd}"/>
<MenuItem Header="Удалить напоминание"
Command="{Binding ReminderDeleteCmd}"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</DockPanel>
</TabItem>
<TabItem Header="База знаний" FontSize="14"
Style="{StaticResource TabItemCustomStyle}">
</TabItem>
</TabControl>
</DockPanel>
</Window> |
|
Код "всплывающего окна"
| XML |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
| <Window x:Class="Memory_Refresher.Views.Windows.AlarmWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Memory_Refresher.Views.Windows"
Title="AlarmWindow" Height="250" Width="450"
WindowStartupLocation="Manual">
<DockPanel Background="#FFE6FFFB">
<StackPanel DockPanel.Dock="Top">
<TextBlock FontSize="20"
Text="Внимание!"
TextWrapping="Wrap"
TextAlignment="Center"
VerticalAlignment="Center"
FontFamily="Monotype Corsiva"
FontWeight="Bold"
FontStyle="Normal"
Foreground="#FF5A00FF">
<TextBlock.Background>
<LinearGradientBrush>
<GradientStop Color="#ff3f00" Offset = "0.2"/>
<GradientStop Color="#ff7200" Offset="0.3"/>
<GradientStop Color="#ff7200" Offset="0.4"/>
<GradientStop Color="#ffd800" Offset="0.5"/>
<GradientStop Color="#ff7200" Offset="0.6"/>
<GradientStop Color="#ff7200" Offset="0.7"/>
<GradientStop Color="#ff3f00" Offset="0.8"/>
</LinearGradientBrush>
</TextBlock.Background>
</TextBlock>
</StackPanel>
<StackPanel DockPanel.Dock="Top">
<TextBlock FontSize="20"
Text="Сработало напоминание!"
TextWrapping="Wrap"
TextAlignment="Center"
VerticalAlignment="Center"
FontFamily="Monotype Corsiva"
FontWeight="Bold"
FontStyle="Normal"
Foreground="#FF5A00FF"
Margin="0,-1,0,-1">
<TextBlock.Background>
<LinearGradientBrush>
<GradientStop Color="#ff3f00" Offset = "0.2"/>
<GradientStop Color="#ff7200" Offset="0.3"/>
<GradientStop Color="#ff7200" Offset="0.4"/>
<GradientStop Color="#ffd800" Offset="0.5"/>
<GradientStop Color="#ff7200" Offset="0.6"/>
<GradientStop Color="#ff7200" Offset="0.7"/>
<GradientStop Color="#ff3f00" Offset="0.8"/>
</LinearGradientBrush>
</TextBlock.Background>
</TextBlock>
</StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.7*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="0.4*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0"
Margin="5"
IsReadOnly="True"
BorderThickness="0.5"
BorderBrush="#FF0D1BF3"/>
<TextBox Grid.Row="1"
Margin="5"
IsReadOnly="True"
BorderThickness="0.5"
BorderBrush="#FF0D1BF3"/>
<Button Grid.Row="2"
Content="Отложить"
VerticalAlignment="Center"
HorizontalAlignment="Left"
FontSize="12"
Height="24"
Margin="5,5,5,5"
Padding="5,0,5,0"
Style="{StaticResource RemoveButtonStyle}"/>
<Button Grid.Row="2"
Content="Выключить"
VerticalAlignment="Center"
HorizontalAlignment="Right"
FontSize="12"
Height="24"
Margin="5"
Padding="5,0,5,0"
Background="Green"
Style="{StaticResource CheckButtonStyle}"/>
</Grid>
</DockPanel>
</Window> |
|
VM главного окна
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
| internal class MainWindow_VM : Base_VM, IDownloadReminders
{
#region заголовок окна
private string _Tittle = "Memory Refresher++";
/// <summary>Заголовок окна </summary>
public string Tittle
{
get => _Tittle;
set => Set(ref _Tittle, value);
}
#endregion
#region Свойства, привязанные к онку
public Reminder SelectedReminder { get; set; }
#endregion
#region Команды
#region Сохранение в файл
//Команда сохранения в файл
public ICommand SaveRemindersCmd { get; }
private bool CanSaveRemindersCmdExecute(object p) => true;
private void OnSaveRemindersCmdExecuted(object p)
{
ISaveReminders(Collections.Reminders);
}
#endregion //Сохранение в файл
#region Команда на статус "Напомнинание выполнено"
public ICommand ReminderCompletedCmd { get; }
private bool CanReminderCompletedCmdExecute(object p) => true;
private void OnReminderCompletedCmdExecuted(object p)
{
IReminderCompleted(SelectedReminder, Collections.Reminders);
}
#endregion //Команда на статус "Напомнинание выполнено"
#region Удаление напоминания из файла
public ICommand ReminderDeleteCmd { get; }
private bool CanReminderDeleteCmdExecute(object p) => true;
private void OnReminderDeleteCmdExecuted(object p)
{
IReminderDelete(SelectedReminder, Collections.Reminders);
}
#endregion
#region Команда сохранения и закрытия приложения
public ICommand CloseApp { get; }
private bool CanCloseAppExecute(object p) => true;
private void OnCloseAppExecuted(object p)
{
ISaveReminders(Collections.Reminders);
System.Windows.Application.Current.Shutdown();
}
#endregion
#endregion //команды
#region Конструктор
public MainWindow_VM()
{
//new Thread(() => IDownloadReminders(Collections.Reminders)).Start();
IDownloadReminders(Collections.Reminders);
NextReminderTime(Collections.Reminders);
CloseApp = new LamdaCommand(OnCloseAppExecuted, CanCloseAppExecute);
ReminderDeleteCmd = new LamdaCommand(OnReminderDeleteCmdExecuted, CanReminderDeleteCmdExecute);
SaveRemindersCmd = new LamdaCommand(OnSaveRemindersCmdExecuted, CanSaveRemindersCmdExecute);
ReminderCompletedCmd = new LamdaCommand(OnReminderCompletedCmdExecuted, CanReminderCompletedCmdExecute);
}
#endregion
#region методы
//метод возвращает интервал времени в минутах для ближайшего напоминания (используется для таймера)
private double NextReminderTime(ObservableCollection<Reminder> Reminders)
{
double x = 0;
if (Reminders.Count != 0)
{
Reminder rem = Reminders[0];
TimeSpan interval = (DateTime.Now - rem.DateTimeReminder).Duration();
x = interval.TotalMinutes;
}
return x;
}
#endregion
#region Реализация интерфейса IDownloadReminders
//сохранение в файл
public void ISaveReminders(ObservableCollection<Reminder> collections)
{
var exePath = AppDomain.CurrentDomain.BaseDirectory;
var path = Path.Combine(exePath + @"\..\..\Data\Reminders\");
var options = new JsonSerializerOptions
{
WriteIndented = true
};
string json = JsonSerializer.Serialize(collections, options);
File.WriteAllText(path + @"reminders.json", json);
}
//загрузка из файла
public void IDownloadReminders(ObservableCollection<Reminder> collection)
{
string exePath = AppDomain.CurrentDomain.BaseDirectory;
string path = Path.Combine(exePath + @"\..\..\Data\Reminders\");
string jsonString = File.ReadAllText(path + @"reminders.json");
try
{
var remiders = JsonSerializer.Deserialize<ObservableCollection<Reminder>>(jsonString);
foreach (Reminder reminder in remiders)
{
Reminder rem1 = new Reminder();
if(reminder.statusReminder == false)
{
rem1 = reminder;
}
else { break; }
collection.Add(rem1);
}
}
catch
{
return;
}
}
//присваивание напоминанию статуса выполнено и исключение из коллекции
public void IReminderCompleted(Reminder SelectReminder, ObservableCollection<Reminder> collection)
{
SelectedReminder.statusReminder = true;
collection.Remove(SelectReminder);
}
//удаление напоминания
public void IReminderDelete(Reminder SelectReminder, ObservableCollection<Reminder> collection)
{
collection.Remove(SelectReminder);
//ISaveReminders(collection);
}
} |
|
Класс "Базовой команды"
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
| internal abstract class BaseCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public abstract bool CanExecute(object parameter);
public abstract void Execute(object parameter);
} |
|
Команда открытия "Всплывающего окна". На данный момент привязана к кнопке в MainWindow
| C# |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| internal class OpenAlarmWindowCommand : BaseCommand
{
double workHeight = SystemParameters.FullPrimaryScreenHeight;
double workWidth = SystemParameters.FullPrimaryScreenWidth;
private AlarmWindow _Window;
public override bool CanExecute(object parameter) => _Window == null;
public override void Execute(object parameter)
{
AlarmWindow window = new AlarmWindow();
_Window = window;
window.Top = workHeight-220;
window.Left = workWidth-450;
window.Owner = Application.Current.MainWindow;
window.Closed += OnWindowClosed;
window.Show();
}
private void OnWindowClosed(object Sender, EventArgs E)
{
((Window)Sender).Closed -= OnWindowClosed;
_Window = null;
}
} |
|