简单说明如何清理WPF中的非托管资源

时间:2014-07-05 19:54:33

标签: c# wpf

我有一个使用MVVM Light的应用程序启动另一个应用程序,当用户关闭主应用程序时我需要停止该应用程序。

我创建了一个释放资源的Dispose()方法,但我不明白的是我调用 Dispose()。

例如,我注意到在Application类定义中有: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 个答案:

答案 0 :(得分:1)

您可以处理MainWindow的Closing事件并在那里进行处理。

<强> XAML

<Window Closing="Window_Closing">

代码

private void Window_Closing(object sender, CancelEventArgs e)
{
   // Clean up your resources here.
}