#c# #wpf
#c# #wpf
Вопрос:
У меня есть приложение, использующее MVVM Light, которое запускает другое приложение, которое мне нужно остановить, когда пользователь закрывает основное приложение.
Я создал метод Dispose (), который освобождает ресурсы, но чего я не понимаю, так это того, где я вызываю Dispose() .
Например, я заметил, что в определении класса приложения есть: public event ExitEventHandler Exit;
Могу ли я добавить что-то в свое приложение (см. Код ниже), которое запускается при завершении работы приложения?
(Я знаю, что есть много других вопросов по этой теме, но все они, похоже, предполагают больше знаний c #)
App.xaml.cs…
namespace Module.Config
{
public partial class App : Application
{
static App()
{
DispatcherHelper.Initialize();
}
}
}
MainWindow.xaml…
<Window x:Class="Module.Config.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"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.ignore.com"
mc:Ignorable="d ignore"
Height="640" MinHeight="600"
Width="800" MinWidth="800"
Title="Config"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Closing="Window_Closing"
>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="LayoutRoot" Margin="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding Side}" Grid.Column="0" />
<ContentControl Content="{Binding SelectedModule}" Grid.Column="1" />
</Grid>
</Window>
MainWindow.xaml.cs…
namespace Module.Config
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Closing = (s, e) => ViewModelLocator.Cleanup();
Messenger.Default.Register<DialogMessage>(
this,
msg =>
{
var result = MessageBox.Show(
msg.Content,
msg.Caption,
msg.Button
);
msg.ProcessCallback(result);
});
. . . . .
private void Window_Closing(object sender, CancelEventArgs e)
{
/*
I want to call Dispose() within AvigilonViewModel.cs
*/
}
}
}
AvigilonView.xaml…
<UserControl x:Class="Module.Config.Views.Modules.AvigilonView"
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"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:Module.Config"
xmlns:ignore="http://www.ignore.com"
mc:Ignorable="d ignore"
DataContext="{Binding Avigilon, Source={StaticResource Locator}}">
<Grid>
.....
AvigilonView.xaml.cs…
namespace Module.Config.Views.Modules
{
public partial class AvigilonView : UserControl
{
public AvigilonView()
{
InitializeComponent();
}
}
}
MainViewModel.cs……
namespace Module.Config.ViewModel
{
public class MainViewModel : ViewModelBase
{
private ViewModelBase m_selectedModule;
public ViewModelBase Side
{
get { return ServiceLocator.Current.GetInstance<SideViewModel>(); }
}
public ViewModelBase SelectedModule
{
get { return m_selectedModule; }
set
{
m_selectedModule = value;
RaisePropertyChanged("SelectedModule");
}
}
public MainViewModel()
{
Messenger.Default.Register<PropertyChangedMessage<object>>(this, (r) =>
{
if (r.PropertyName == "SelectedNode")
{
if (r.NewValue is RedSensor)
{
SelectedModule = ServiceLocator.Current.GetInstance<SensorViewModel>();
(SelectedModule as SensorViewModel).Sensor = r.NewValue as RedSensor;
}
else
{
SelectedModule = r.NewValue as ViewModelBase;
}
}
});
}
}
}
AvigilonViewModel.cs….
namespace Module.Config.ViewModel.Modules
{
public class AvigilonViewModel : ViewModelBase
{
....
public Dispose(){
/* code to get rid of unmanaged resources */
}
}
}
ViewModelLocator.cs…
namespace Module.Config.ViewModel
{
public class ViewModelLocator
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
//SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
//SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<AppState>();
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<SideViewModel>();
SimpleIoc.Default.Register<AvigilonViewModel>();
}
/// <summary>
/// Gets the Main property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public SideViewModel Side
{
get
{
return ServiceLocator.Current.GetInstance<SideViewModel>();
}
}
/// <summary>
/// Gets the Main property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public AvigilonViewModel Avigilon
{
get
{
return ServiceLocator.Current.GetInstance<AvigilonViewModel>();
}
}
....
Я также заметил строку Closing = (s, e) => ViewModelLocator.Cleanup();
в приведенном выше. Я попытался добавить метод с именем `Cleanup() в AvigilonView.xaml.cs и AvigilonViewModel.cs, но, похоже, он не вызывается.
Ответ №1:
Вы можете обработать Closing
событие вашего MainWindow и выполнить обработку там.
XAML:
<Window Closing="Window_Closing">
Код, лежащий в основе:
private void Window_Closing(object sender, CancelEventArgs e)
{
// Clean up your resources here.
}
Комментарии:
1. Большое спасибо. Однако я все еще могу понять, как ссылаться на мои ViewModels в методе Windows_Closing (для вызова Dispose), например. если у меня есть файл XAML, который запускается:
<UserControl x:Class="Module.Config.Views.Modules.AvigilonView"....
Как мне определить имя объекта для этого класса?2. Если у вас есть экземпляр View, вы можете получить доступ к его ViewModel, обратившись к
DataContext
свойству View. eg —avigilonView.DataContext as AvigilonViewModel
.3. Спасибо, но что вы имеете в виду под
instance of View
? Вы имеете в виду, что я должен создать экземпляр View? Я попробовал это, но получил:The type or namespace name 'View' could not be found (are you missing a using directive or an assembly reference?)
Для avigilonView написаноThe name 'avigilonView' does not exist in the current context
4. Я не уверен, что вы задумали. Опубликуйте какой-нибудь релевантный код, о каком представлении вы говорите? Вы должны показать некоторый код. Прямо сейчас очень сложно комментировать, не видя вашего кода. (Вопрос касается только того, куда поместить очищающий код).
5.ок, наконец, разобрался. В Window_Closing() Я добавил
var theAvililonViewModel = ServiceLocator.Current.GetInstance<AvigilonViewModel>();
theAvililonViewModel.Dispose();