Subscribed events fires twice?.....

Topics: Prism v4 - WPF 4
Apr 23, 2013 at 4:27 PM
Hi,

Need help as to why my event is firing twice. I publish the event only in two places and it only gets fired once after the main Window is loaded and the other is after I loaded a new file using the OpenDialog Dialog. Both are in my ShellViewModel.

ShellViewModel.cs:
        private void ShowOpenFileDialog(object arg)
        {
            string getFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

            if (!string.IsNullOrWhiteSpace(this.DirectoryPath))
                getFolderPath = this.DirectoryPath;

            var openFileDialog = new OpenFileDialog()
            {
                InitialDirectory = getFolderPath,
                FileName = this.DocumentFileName,
                DefaultExt = "*.ods",
                Filter = "Open Document Spreadsheet (.ods)|*.ods"
            };

            if (openFileDialog.ShowDialog() == true)
            {
                DirectoryInfo di = new DirectoryInfo(openFileDialog.FileName);
                DocumentFileInfo dfInfo = new DocumentFileInfo();

                this.InputPath = openFileDialog.FileName;
                this.DirectoryPath = di.Parent.FullName;
                this.DocumentFileName = di.Name;
                this.IsSpreadsheetML = true;

                eventAggregator.GetEvent<DocumentFileEvent>().Publish(new DocumentFileInfo
                {
                    InputPath = this.InputPath,
                    DirectoryPath = this.DirectoryPath,
                    DocumentFileName = this.DocumentFileName
                });
            }
        }

        public void OnNatsarLoaded()
        {
            //MessageBox.Show("OnNatsarLoaded called");
            if (!string.IsNullOrWhiteSpace(Settings.Default.InputPath))
            {
                this.InputPath = Settings.Default.InputPath;

                if (!File.Exists(this.InputPath))
                    return;

                if (string.IsNullOrWhiteSpace(this.directoryPath))
                    return;

                this.DirectoryPath = Settings.Default.DirectoryPath;

                if (string.IsNullOrWhiteSpace(this.documentFileName))
                    return;

                this.DocumentFileName = Settings.Default.DocumentFileName;

                DocumentFileInfo dfInfo = new DocumentFileInfo();
                this.IsSpreadsheetML = true;

 __               eventAggregator.GetEvent<DocumentFileEvent>().Publish(new DocumentFileInfo
                {
                    InputPath = this.InputPath,
                    DirectoryPath = this.DirectoryPath,
                    DocumentFileName = this.DocumentFileName
                });
__            }
        }
...the event is subscribed in two places, 1) where is processes the file information.

ObservablePosition.cs
          eventAggregator.GetEvent<DocumentFileEvent>().Subscribe(OnDocumentFileEvent, ThreadOption.UIThread);

        private void OnDocumentFileEvent(DocumentFileInfo dfInfo)
        {
            this.HeaderInfo = dfInfo.DocumentFileName.ToUpper();
            //MessageBox.Show("OnDocumentFileEvent : " + dfInfo.DocumentFileName);
            try
            {
                using (ZipFile zipFile = ZipFile.Read(dfInfo.InputPath))
                {
                    zipFile.ExtractProgress += this.odsProgressHandler.ExtractProgressHandler;

                    OdsZipFileUpdated(new OdsNewDocumentInfo
                    {
                        AddDirectoryWillTraverseReparsePoints = zipFile.AddDirectoryWillTraverseReparsePoints,
                        AlternateEncoding = zipFile.AlternateEncoding,
                        AlternateEncodingUsage = zipFile.AlternateEncodingUsage,
                        BufferSize = zipFile.BufferSize,
                        CaseSensitiveRetrieval = zipFile.CaseSensitiveRetrieval,
                        CodecBufferSize = zipFile.CodecBufferSize,
                        Comment = zipFile.Comment,
                        CompressionLevel = zipFile.CompressionLevel,
                        CompressionMethod = zipFile.CompressionMethod,
                        Count = zipFile.Count,
                        EmitTimesInUnixFormatWhenSaving = zipFile.EmitTimesInUnixFormatWhenSaving,
                        EmitTimesInWindowsFormatWhenSaving = zipFile.EmitTimesInWindowsFormatWhenSaving,
                        Encryption = zipFile.Encryption,
                        Entries = zipFile.Entries,
                        EntriesSorted = zipFile.EntriesSorted,
                        EntryFileNames = zipFile.EntryFileNames,
                        ExtractExistingFile = zipFile.ExtractExistingFile,
                        FlattenFoldersOnExtract = zipFile.FlattenFoldersOnExtract,
                        FullScan = zipFile.FullScan,
                        Info = zipFile.Info,
                        InputUsesZip64 = zipFile.InputUsesZip64,
                        //LibraryVersion = assemName.Version,
                        MaxOutputSegmentSize = zipFile.MaxOutputSegmentSize,
                        Name = zipFile.Name,
                        NumberOfSegmentsForMostRecentSave = zipFile.NumberOfSegmentsForMostRecentSave,
                        OutputUsedZip64 = zipFile.OutputUsedZip64,
                        ParallelDeflateMaxBufferPairs = zipFile.ParallelDeflateMaxBufferPairs,
                        ParallelDeflateThreshold = zipFile.ParallelDeflateThreshold,
                        //Password = zipFile.Password,
                        RequiresZip64 = zipFile.RequiresZip64,
                        SetCompression = zipFile.SetCompression,
                        SortEntriesBeforeSaving = zipFile.SortEntriesBeforeSaving,
                        StatusMessageTextWriter = zipFile.StatusMessageTextWriter,
                        Strategy = zipFile.Strategy,
                        TempFileFolder = zipFile.TempFileFolder,
                        UseZip64WhenSaving = zipFile.UseZip64WhenSaving,
                        ZipErrorAction = zipFile.ZipErrorAction,
                        ZipFile = zipFile
                    });
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error reading file {0}", e.Message);
                MessageBox.Show(e.Message, "Error reading file");
            }
        }

        private void OdsZipFileUpdated(OdsNewDocumentInfo zfInfo)
        {
            this.OdsItems.Clear();

            foreach (ZipEntry z in zfInfo.Entries)
            {
                if (z.CompressedSize != 0)
                {
                    this.OdsItems.Add(new OdsEntrySummaryItem(z)
                    {
                        FileName = z.FileName,
                        CompressedSize = z.CompressedSize,
                        CompressionRatio = z.CompressionRatio,
                        Crc = z.Crc,
                        UncompressedSize = z.UncompressedSize,
                        CreationTime = z.CreationTime,
                        ZipFile = zfInfo.ZipFile
                    });
                }
            }
        }
..., 2) is where I get the file name for the header tab
PositionSummaryViewModel.cs:
            eventAggregator.GetEvent<DocumentFileEvent>().Subscribe(OnHeaderInfoEvent, ThreadOption.UIThread);

        public string HeaderInfo
        {
            get { return this.headerInfo; }
            set { this.headerInfo = value; this.RaisePropertyChanged(() => HeaderInfo); }
        }

        private void OnHeaderInfoEvent(DocumentFileInfo dfInfo)
        {
            this.HeaderInfo = dfInfo.DocumentFileName.ToUpper();
        }
So us this something in Prism or me?
Developer
Apr 23, 2013 at 8:17 PM
Hi,

After checking the code snippets you posted I couldn't find anything that would cause the event to be raised twice, so the problem might not be in these parts of the code.

As a starting point to find the cause behind this, please check in your application that:
  • The methods where the event is published are not being executed twice.
  • The subscribers were not subscribed to the event twice.
  • There are no duplicates of the subscribed objects either alive or waiting to be destroyed.
Regards,

Damian Cherubini
http://blogs.southworks.net/dcherubini
Apr 24, 2013 at 4:44 PM
Thanks for the reply! :)

Well I did find of that IObservablePosition is being initialize twice, so I have to find out how and where its being done.

PositionSummaryViewModel.cs:
        public PositionSummaryViewModel(IOrdersController ordersController, IEventAggregator eventAggregator, IObservablePosition observablePosition)
        {
            if (ordersController == null)
            {
                throw new ArgumentNullException("ordersController");
            }

            this.eventAggregator = eventAggregator;
            this.Position = observablePosition;

            BuyCommand = ordersController.EntryCommand;
            SellCommand = ordersController.RemoveEntryCommand;

            this.CurrentPositionSummaryItem = new PositionSummaryItem("FAKEINDEX", 0, 0, 0);

            eventAggregator.GetEvent<DocumentFileEvent>().Subscribe(OnHeaderInfoEvent, ThreadOption.UIThread);
        }
PositionPieChartViewModel.cs:
        public PositionPieChartViewModel(IObservablePosition observablePosition)
        {
            this.Position = observablePosition;
        }
is it because of the Attributes of:
    [Export(typeof(IObservablePosition))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ObservablePosition : NotificationObject, IObservablePosition
... that cause the class to be initialize by the calling class and do I need to change this to Shared? Because I only want one instance of this class.
Apr 24, 2013 at 5:44 PM
Yes, that was it, it working fine now. The way my structure is, is that I need that object to be initialized once.
Developer
Apr 24, 2013 at 8:17 PM
Hi,

I'm glad to hear that you could find the cause behind this behavior. Indeed, when you want to have only one instance of an exported type in the application (e.g. a singleton,) you will need to define the CreationPolicy as Shared. When the type is exported as NonShared, a new instance will be created each time it's injected as a dependency by the container.

Regards,

Damian Cherubini
http://blogs.southworks.net/dcherubini