VSTO Outlook Add-in Event Handers not firing on start up - c#

enter code hereI have an VSTO add in that is intercepting custom events. I have event handlers. I am looking for Add, Edit and Delete Items on the default calendar folder in outlook.
I have a button for creating custom appointments and after that is pressed the event handlers work fine but I need the event handlers to function from start up to catch custom events created in the previous session and they are not always firing at start up.
Here is some example code.
public partial class ThisAddIn
{
public string subjectName;
public Outlook.AppointmentItem apptItem;
public Outlook.Folder calendarFolder;
Outlook.Items items;
bool m_IsFirstTime = false;
CalendarMonitor calendarMonitor;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
calendarMonitor = new CalendarMonitor(Application.ActiveExplorer());
calendarMonitor.AppointmentAdded += new EventHandler<EventArgs<AppointmentItem>>(Monitor_AppointmentAdded);
calendarMonitor.AppointmentModified += new EventHandler<EventArgs<AppointmentItem>>(Monitor_AppointmentModified);
calendarMonitor.AppointmentDeleting += new EventHandler<CancelEventArgs<AppointmentItem>>(Monitor_AppointmentDeleting);
Application.Inspectors.NewInspector += Inspectors_NewInspector;
Outlook.NameSpace ns = Application.Session;
calendarFolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) as Outlook.Folder;
items = calendarFolder.Items;
items.ItemChange += new Microsoft.Office.Interop.Outlook.ItemsEvents_ItemChangeEventHandler(Items_ItemChange);
}
}
//Calendar Monitor class
public class CalendarMonitor
{
private Explorer m_explorer;
private List<string> m_folderPaths;
private List<MAPIFolder> m_calendarFolders;
private List<Items> m_calendarItems;
private MAPIFolder m_deletedItemsFolder;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentAdded;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentModified;
public event EventHandler<CancelEventArgs<AppointmentItem>> AppointmentDeleting;
public CalendarMonitor(Explorer anExplorer)
{
m_folderPaths = new List<string>();
m_calendarFolders = new List<MAPIFolder>();
m_calendarItems = new List<Items>();
m_explorer = anExplorer;
m_explorer.BeforeFolderSwitch +=
new ExplorerEvents_10_BeforeFolderSwitchEventHandler(Explorer_BeforeFolderSwitch);
NameSpace session = m_explorer.Session;
try
{
m_deletedItemsFolder = session.GetDefaultFolder(OlDefaultFolders.olFolderDeletedItems);
HookupDefaultCalendarEvents(session);
}
finally
{
Marshal.ReleaseComObject(session);
session = null;
}
}
private void HookupDefaultCalendarEvents(NameSpace aSession)
{
MAPIFolder folder = aSession.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
if (folder != null)
{
try
{
HookupCalendarEvents(folder);
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
}
private void Explorer_BeforeFolderSwitch(object aNewFolder, ref bool Cancel)
{
MAPIFolder folder = (aNewFolder as MAPIFolder);
//
// Hookup events to any other Calendar folder opened.
//
if (folder != null)
{
try
{
if (folder.DefaultItemType == OlItemType.olAppointmentItem)
{
HookupCalendarEvents(folder);
}
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
}
private void HookupCalendarEvents(MAPIFolder aCalendarFolder)
{
if (aCalendarFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder must use " +
"AppointmentItems as the default type.");
}
//
// Ignore other user's calendars.
//
if ((m_folderPaths.Contains(aCalendarFolder.FolderPath) == false)
&& (IsUsersCalendar(aCalendarFolder)))
{
Items items = aCalendarFolder.Items;
//
// Store folder path to prevent double ups on our listeners.
//
m_folderPaths.Add(aCalendarFolder.FolderPath);
//
// Store a reference to the folder and to the items collection so that it remains alive for
// as long as we want. This keeps the ref count up on the underlying COM object and prevents
// it from being intermittently released (then the events don't get fired).
//
m_calendarFolders.Add(aCalendarFolder);
m_calendarItems.Add(items);
//
// Add listeners for the events we need.
//
((MAPIFolderEvents_12_Event)aCalendarFolder).BeforeItemMove +=
new MAPIFolderEvents_12_BeforeItemMoveEventHandler(Calendar_BeforeItemMove);
items.ItemChange += new ItemsEvents_ItemChangeEventHandler(CalendarItems_ItemChange);
items.ItemAdd += new ItemsEvents_ItemAddEventHandler(CalendarItems_ItemAdd);
}
}
private void CalendarItems_ItemAdd(object anItem)
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentAdded != null)
{
this.AppointmentAdded(this, new EventArgs<AppointmentItem>(appointment));
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
private void CalendarItems_ItemChange(object anItem)
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentModified != null)
{
this.AppointmentModified(this, new EventArgs<AppointmentItem>(appointment));
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
private void Calendar_BeforeItemMove(object anItem, MAPIFolder aMoveToFolder, ref bool Cancel)
{
if ((aMoveToFolder == null) || (IsDeletedItemsFolder(aMoveToFolder)))
{
AppointmentItem appointment = (anItem as AppointmentItem);
if (appointment != null)
{
try
{
if (this.AppointmentDeleting != null)
{
//
// Listeners to the AppointmentDeleting event can cancel the move operation if moving
// to the deleted items folder.
//
CancelEventArgs<AppointmentItem> args = new CancelEventArgs<AppointmentItem>(appointment);
this.AppointmentDeleting(this, args);
Cancel = args.Cancel;
}
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
}
}
private bool IsUsersCalendar(MAPIFolder aFolder)
{
return (aFolder.Store != null);
}
private bool IsDeletedItemsFolder(MAPIFolder aFolder)
{
return (aFolder.EntryID == m_deletedItemsFolder.EntryID);
}
}

You need to keep the source objects alive if you want to get events fired correctly:
Application.Inspectors.NewInspector += Inspectors_NewInspector;
Instead, declare the Inspectors instance at the class level:
Application.Inspectors inspectors = null;
// in the method you could use the following code
inspectors = Application.Inspectors;
inspectors.NewInspector += Inspectors_NewInspector;
Define the object (Inspectors) at the class level to prevent it from swiping by the garbage collector.
You may find the Implement a wrapper for inspectors and track item-level events in each inspector article helpful.
For example, the following code is a good sample to explain a possible issue:
private void HookupCalendarEvents(MAPIFolder aCalendarFolder)
{
if (aCalendarFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder must use " +
"AppointmentItems as the default type.");
}
//
// Ignore other user's calendars.
//
if ((m_folderPaths.Contains(aCalendarFolder.FolderPath) == false)
&& (IsUsersCalendar(aCalendarFolder)))
{
Items items = aCalendarFolder.Items;
//
// Store folder path to prevent double ups on our listeners.
//
m_folderPaths.Add(aCalendarFolder.FolderPath);
//
// Store a reference to the folder and to the items collection so that it remains alive for
// as long as we want. This keeps the ref count up on the underlying COM object and prevents
// it from being intermittently released (then the events don't get fired).
//
m_calendarFolders.Add(aCalendarFolder);
m_calendarItems.Add(items);
//
// Add listeners for the events we need.
//
((MAPIFolderEvents_12_Event)aCalendarFolder).BeforeItemMove +=
new MAPIFolderEvents_12_BeforeItemMoveEventHandler(Calendar_BeforeItemMove);
items.ItemChange += new ItemsEvents_ItemChangeEventHandler(CalendarItems_ItemChange);
items.ItemAdd += new ItemsEvents_ItemAddEventHandler(CalendarItems_ItemAdd);
}
}
The Items object is defined inside the method, so when the GC triggers the object can be swiped from the heap (if method finished its work). So, you will never get events fired after that. To prevent this from happening you need to declare the source object at the class level:
Items items = null;
private void HookupCalendarEvents(MAPIFolder aCalendarFolder)
{
if (aCalendarFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder must use " +
"AppointmentItems as the default type.");
}
//
// Ignore other user's calendars.
//
if ((m_folderPaths.Contains(aCalendarFolder.FolderPath) == false)
&& (IsUsersCalendar(aCalendarFolder)))
{
items = aCalendarFolder.Items;
//
// Store folder path to prevent double ups on our listeners.
//
m_folderPaths.Add(aCalendarFolder.FolderPath);
//
// Store a reference to the folder and to the items collection so that it remains alive for
// as long as we want. This keeps the ref count up on the underlying COM object and prevents
// it from being intermittently released (then the events don't get fired).
//
m_calendarFolders.Add(aCalendarFolder);
m_calendarItems.Add(items);
//
// Add listeners for the events we need.
//
((MAPIFolderEvents_12_Event)aCalendarFolder).BeforeItemMove +=
new MAPIFolderEvents_12_BeforeItemMoveEventHandler(Calendar_BeforeItemMove);
items.ItemChange += new ItemsEvents_ItemChangeEventHandler(CalendarItems_ItemChange);
items.ItemAdd += new ItemsEvents_ItemAddEventHandler(CalendarItems_ItemAdd);
}
}

Related

WMPLib Music plays but when I switch tabs it stops [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have C# application for a Food Truck. I have some music playing when customers view the menu. On the menu form I have four tabs. I have the WMPLib code in form load. When the form loads the music begins playing however when I switch to a different tab the music stops. I have debugged but there is nothing there to really see since it runs the lines but just stops when you switch tabs. Any ideas on how to keep the music playing when switching tabs on the main form. I would like it to play continuous not just start again on each tab. Thanks. Here is an image of the form with the tabs.
Here is the form load code:
try
{
WMPLib.WindowsMediaPlayer wplayer = new WMPLib.WindowsMediaPlayer();
wplayer.URL = "runningdownadream.mp3";
wplayer.settings.setMode("loop", true);
wplayer.controls.play();
}
catch (Exception ex)
{
MessageBox.Show("No music. Windows Media Player not installed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
In order to play an MP3 in the background using WMPLib, try the following:
Create a class (name: HelperMp3.cs)
HelperMp3.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AxWMPLib;
using System.Diagnostics;
namespace WmpLibTest
{
public class HelperMp3 : IDisposable
{
public delegate void EventHandlerMediaError(object sender, object pMediaObject);
public delegate void EventHandlerPlayStateChanged(object sender, int newValue);
//events
public event EventHandlerMediaError Mp3MediaError;
public event EventHandlerPlayStateChanged Mp3PlayStateChanged;
public string MP3Filename { get; set; } //fully-qualified MP3 filename
private WMPLib.WindowsMediaPlayer _wplayer = new WMPLib.WindowsMediaPlayer();
public HelperMp3()
{
//subscribe to events (add event handlers)
_wplayer.PlayStateChange += _wplayer_PlayStateChange;
_wplayer.MediaError += _wplayer_MediaError;
}
private void _wplayer_MediaError(object pMediaObject)
{
System.Diagnostics.Debug.WriteLine("Error (MediaError): " + pMediaObject.ToString());
//if subscribed to event, raise event, otherwise throw exception
if (Mp3MediaError != null)
{
//raise event
Mp3MediaError(this, pMediaObject);
}
else
{
throw new Exception("Error (MediaError): " + pMediaObject.ToString());
}
}
private void _wplayer_PlayStateChange(int NewState)
{
//Undefined = 0,
//Stopped = 1,
//Paused = 2,
//Playing = 3,
//ScanForward = 4,
//ScanReverse = 5,
//Buffering = 6,
//Waiting = 7,
//MediaEnded = 8,
//Transitioning = 9,
//Ready = 10,
//Reconnecting = 11,
//Last = 12
if (Mp3PlayStateChanged != null)
{
//raise event
Mp3PlayStateChanged(this, NewState);
}
System.Diagnostics.Debug.WriteLine("_wplayer_PlayStateChange: " + NewState.ToString());
}
public void Dispose()
{
if (_wplayer != null)
{
_wplayer.controls.stop();
//unsubscribe from events (add event handlers)
_wplayer.PlayStateChange -= _wplayer_PlayStateChange;
_wplayer.MediaError -= _wplayer_MediaError;
//release all resources
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(_wplayer);
_wplayer = null;
}
}
public void Start()
{
if (_wplayer != null)
{
_wplayer.controls.play();
}
}
public void Stop()
{
if (_wplayer != null)
{
_wplayer.controls.stop();
}
}
public void PlayMp3()
{
Debug.WriteLine("MP3Filename: " + MP3Filename);
if (String.IsNullOrEmpty(MP3Filename) || !System.IO.File.Exists(MP3Filename))
{
throw new Exception("MP3Filename not specified.");
}
Debug.WriteLine("Playing mp3...");
//set value
_wplayer.URL = MP3Filename;
_wplayer.settings.setMode("loop", true);
_wplayer.controls.play();
}
}
}
In the form (ex: Form1) code, create an instance of the class above:
private HelperMp3 _helperMp3 = new HelperMp3();
Then create a method that starts the music:
private void StartMusic(string mp3Filename)
{
//set property
helperMp3.MP3Filename = mp3Filename;
Task t1 = Task.Run(_helperMp3.PlayMp3);
}
Subscribe to the Load event for the form (ex: Form1_Load) and add the following code:
private void Form1_Load(object sender, EventArgs e)
{
//ToDo: replace with your MP3 filename
StartMusic(#"C:\Temp\Test.mp3");
}
Subscribe to the FormClosed event for the form (ex: Form1_FormClosed) and add the following code:
Form1_FormClosed
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (_helperMp3 != null)
{
_helperMp3.Dispose();
_helperMp3 = null;
}
}
Alternatively, one can use BackgroundWorker. If using BackgroundWorker, in HelperMp3.cs change method PlayMp3 to the following:
public void PlayMp3(System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
{
Debug.WriteLine("MP3Filename: " + MP3Filename);
if (String.IsNullOrEmpty(MP3Filename) || !System.IO.File.Exists(MP3Filename))
{
throw new Exception("MP3Filename not specified.");
}
if (worker.CancellationPending || e.Cancel)
{
e.Cancel = true;
}
Debug.WriteLine("Playing mp3...");
//set value
_wplayer.URL = MP3Filename;
_wplayer.settings.setMode("loop", true);
_wplayer.controls.play();
}
Note: If using BackgroundWorker, the BackgroundWorker will complete, but the WMPLib control will still be running.

Prevent MailItem.Reply from opening Inspector window in Outlook 2016

I am building a addin for Outlookto add custom signature in outlook email, when the user click on "Reply" button.
As soon as user click on reply button in explorer, a new inspector opens and i close the inspector with code (which s#cks). There may be a way to totally disable the reply inspector from opening.
private Microsoft.Office.Tools.CustomTaskPane CustomTaskPane;
UserDetail usr = null;
Outlook.Explorer currentExplorer = null;
Outlook.MailItem mailItem;
private Inspector replyInspector;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange +=
new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
if (this.Application.ActiveExplorer().Selection.Count == 1
&& this.Application.ActiveExplorer().Selection[1] is Outlook.MailItem)
{
if (mailItem != null)
{
// when the reply button is clicked
((Outlook.ItemEvents_10_Event)mailItem).Reply -= new Outlook.ItemEvents_10_ReplyEventHandler(MailItem_Reply);
// When an item is selected
Outlook.Selection mySelection = this.Application.ActiveExplorer().Selection;
Outlook.MailItem mailitem = null;
foreach (Object obj in mySelection)
{
if (obj is Outlook.MailItem)
{
mailitem = (Outlook.MailItem)obj;
if (mailitem != null)
{
if (mailitem.Sent)
{
else
{
// Compose
}
}
}
}
}
mailItem = this.Application.ActiveExplorer().Selection[1];
((Outlook.ItemEvents_10_Event)mailItem).Reply += new
Outlook.ItemEvents_10_ReplyEventHandler(MailItem_Reply);
// Close Inspector
replyInspector.Close(OlInspectorClose.olDiscard);
}
else
{
}
}
void MailItem_Reply(Object response, ref bool cancel)
{
try
{
MailItem mitem = (Outlook.MailItem)response;
replyInspector = (mitem).GetInspector;
replyInspector.Activate();
(mitem).HTMLBody = tempSignature + ((Outlook.MailItem)response).HTMLBody;
}
catch (System.Exception e)
{
MessageBox.Show(e.ToString());
}
}
Firstly, why would you want to close the inspector if you are opening it anyway? Why not insert the signature when the inspector is opened?
Secondly, you cannot concatenate two HTML strings and expect the resulting string to be valid HTML, The two needs to be merged. Or, better yet, use Word Object Model (Word.Document is returned from Inspector.WordEditor) to insert any text anywhere in the message body.

Outlook 2010 Addin - change phrase to link without altering email body

I've created simple addin for Outlook 2010 that replace specific phrase with link, for example I want to replace ABC12345 with http://www.example.com?id=123456
I'm using this code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
inspectors = this.Application.Inspectors;
inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
}
void Inspectors_NewInspector(Outlook.Inspector Inspector)
{
var mailItem = Inspector.CurrentItem as Outlook.MailItem;
if (mailItem != null)
{
if (mailItem.EntryID != null)
{
string pattern = #"ABC(?<number>\d{1,6})";
var match = Regex.Match(mailItem.HTMLBody, pattern);
if (match.Success)
{
var replaced = Regex.Replace(mailItem.HTMLBody, pattern, m => "ABC"+ m.Groups["number"].Value+"");
mailItem.HTMLBody = replaced;
}
}
}
}
However I have two issues:
I must double click email in mailbox to have my event fired. I want to display that link when previewing emails (moving up and down in mailbox)
My code is replacing content, so Outlook "thinks" I've made some changes and when I want to close window it asks if I want to save those changes.
I don't want to alter body of email, I want to change phrase ABC123456 into link.
EDIT1:
I've tried using ActiveExplorer, this allows me to access email in preview window, but when I change email body those changes are saved. My intention is to change how specific text is displayed (change it to link), but not to alter email body on serwer.
I want those changes to be visible in my instance of Outlook, not saved on server (mailItem.HTMLBody.Replace does that).
Can I access view that displays email and alter that view?
This is the code:
Outlook.Explorer currentExplorer;
private void ThisAddIn_Startup(object sender, EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
var selectedFolder = this.Application.ActiveExplorer().CurrentFolder;
try
{
if (this.Application.ActiveExplorer().Selection.Count > 0)
{
var selObject = this.Application.ActiveExplorer().Selection[1];
if (selObject is Outlook.MailItem)
{
Outlook.MailItem mailItem = (selObject as Outlook.MailItem);
mailItem.HTMLBody = mailItem.HTMLBody.Replace("ABC", "DEF");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
EDIT2
I'm able to get WordEditor inside Outlook, but I can't add hyperlink.
Last think I want now is to find specific phrases in email and add hyperlink to them. Here is my current code:
Outlook.Explorer currentExplorer;
private void ThisAddIn_Startup(object sender, EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
var selectedFolder = this.Application.ActiveExplorer().CurrentFolder;
try
{
if (this.Application.ActiveExplorer().Selection.Count > 0)
{
var selectedObject = this.Application.ActiveExplorer().Selection[1];
if (selectedObject is Outlook.MailItem)
{
var mail = (selectedObject as Outlook.MailItem);
var inspector = mail.GetInspector;
if (inspector.IsWordMail())
{
var document = (Document)inspector.WordEditor;
if (document != null)
{
var app = document.Application;
var find = document.Range().Find;
find.Text = "ABC";
while (find.Execute())
{
var rng = find.Parent as Range;
rng.Hyperlinks.Add(rng, "http://example.com/?query=" + rng.Text );
rng.Collapse(WdCollapseDirection.wdCollapseEnd);
}
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}

C# WPF Adding items to listview keeps overwriting existing data

I am fairly new to C#. I have a MainWindow which contains a ListView (lvStores), furthermore, I have a button that will open another window (NewStoreWindow). The NewStoreWindow contains 2 textboxes and an OK button. When I write something in the textboxes and press OK, the window is is rightfully closing and adding to my ListView. However, when I try to add a new item to the ListView, after adding the first, it will just overwrite it. Or actually, it will remove it, and then it will add the next one. I believe it has to do with my ObservableCollection. I have tried to put them in my public MainWindow() but then the code wouldn't execute. Furthermore, I have tried to use List instead of ObservableCollection.
Snippet of MainWindow code
private void cmdNewStore_Click(object sender, RoutedEventArgs e)
{
if (m_blnBusy)
{
return;
}
// Open NewStoreWindow in a new window
NewStoreWindow newStore = new NewStoreWindow();
newStore.ShowDialog();
ObservableCollection<AddListViewItem> lvColumnList = new ObservableCollection<AddListViewItem>();
ObservableCollection<AddListViewItem> items = (ObservableCollection<AddListViewItem>)lvStores.ItemsSource;
lvStores.ItemsSource = lvColumnList;
switch (SLvCol)
{
// If CSV is NOT loaded on start up and listview is then empty
case false:
// If no items exist in listview
if (items == null)
{
// Add item from textbox from NewStoreWindow
lvColumnList.Add(new AddListViewItem() {sID = SNewStoreTbid, sName = SNewStoreTbName});
lvStores.ItemsSource = lvColumnList;
// Refresh listview
lvStores.Items.Refresh();
}
else // If items exists
{
if (items != null)
{
bool itemAlreadyAdded = false; // use for boolean checking
foreach (AddListViewItem item in items) // loop through all items in listview
{
//Do some work with the item
MessageBox.Show(item.sID);
if (item.sID == SNewStoreTbid) // Check if new item already exists
{
itemAlreadyAdded = true;
break;
}
if (itemAlreadyAdded) // Show messagebox if it exists
{
MessageBox.Show("ID needs to be unique, please respecify!", "Duplicate ID",
MessageBoxButton.OK, MessageBoxImage.Error);
}
else // if it does not exist, create it from the textbox values
{
lvColumnList.Add(
new AddListViewItem() {sID = SNewStoreTbid, sName = SNewStoreTbName});
lvStores.ItemsSource = lvColumnList;
// refresh listview
//ICollectionView view = CollectionViewSource.GetDefaultView((List<AddListViewItem>)lvStores.ItemsSource);
//view.Refresh();
lvStores.Items.Refresh();
}
}
}
}
break;
.....
}
// Bind textbox values from NewStoreWindow
public class AddListViewItem
{
public string sID { get; set; }
public string sName { get; set; }
}
AddListViewItem item = new AddListViewItem
{
sID = SNewStoreTbid, //SNewStoreTbid,
sName = SNewStoreTbName //SNewStoreTbName
};

My method did not add my file into my list although no error

This is my class that after each file choose add the file to my list and from the main form raise event that update my ListBox and add the file into my ListBox.
when i am choosing 2 files i can see (with the debugger) that the add method add the first file and my list updated but after the second file pass the add method the list.count remained still 1.
public class ListboxFile
{
public delegate void OnFileAdd(string file);
public event OnFileAdd OnFileAddEvent;
private static List<string> _files;
public ListboxFile()
{
_files = new List<string>();
}
public void add(string file)
{
_files.Add(file);
OnFileAddEvent(file);
}
public void remove(string file)
{
if (_files.Contains(file))
{
_files.Remove(file);
}
}
public void clear()
{
_files.Clear();
}
public List<string> list
{
get { return _files; }
}
}
from the main form (add files button click):
private void btnAddfiles_Click(object sender, EventArgs e)
{
#region file filter
string fileToAdd = string.Empty;
System.IO.Stream stream;
OpenFileDialog thisDialog = new OpenFileDialog();
thisDialog.InitialDirectory = (lastPath.Length > 0 ? lastPath : "c:\\");
thisDialog.Filter = "(*.snoop, *.pcap, *.cap, *.net, *.pcapng, *.5vw, *.bfr, *.erf, *.tr1)" +
"|*.snoop; *.pcap; *.cap; *.net; *.pcapng; *.5vw; *.bfr; *.erf; *.tr1|" + "All files (*.*)|*.*";
thisDialog.FilterIndex = 1;
thisDialog.RestoreDirectory = false;
thisDialog.Multiselect = true;
thisDialog.Title = "Please Select Source File";
#endregion
if (thisDialog.ShowDialog() == DialogResult.OK)
{
if (thisDialog.FileNames.Length > 0)
{
lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
}
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork +=
(s3, e3) =>
{
foreach (String file in thisDialog.FileNames)
{
try
{
if ((stream = thisDialog.OpenFile()) != null)
{
int numberOfFiles = thisDialog.SafeFileNames.Length;
using (stream)
{
ListboxFile lbf = new ListboxFile();
lbf.OnFileAddEvent += lbf_OnFileAddEvent;
lbf.checkFile(file);
lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
};
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
(s3, e3) =>
{
});
backgroundWorker.RunWorkerAsync();
}
}
private void lbf_OnFileAddEvent(string file)
{
if (InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
listBoxFiles.Items.Add(file);
, listBoxFiles.Items.Count.ToString("#,##0")));
if (listBoxFiles.Items.Count != 0)
listBoxFiles.SetSelected(listBoxFiles.Items.Count - 1, true);
});
}
else
{
listBoxFiles.Items.Add(file);
if (listBoxFiles.Items.Count != 0)
listBoxFiles.SetSelected(listBoxFiles.Items.Count - 1, true);
}
}
You declare and initialize the instance of ListBoxFile inside the foreach loop.
At every loop you reinitialize the instance and thus you loose the previous add
A fast fix, move the declaration and initialization of the ListboxFile instance outside the loop (also the subscription to the event)
.....
ListboxFile lbf = new ListboxFile();
lbf.OnFileAddEvent += lbf_OnFileAddEvent;
foreach (String file in thisDialog.FileNames)
{
.....
and by the way, you call lbf.checkFile(file);, did you mean lbf.Add(file) right?
You are calling lbf.checkFile(file); but I do not see that method in your class definition. Maybe inside that method you are not firing OnFileAddEvent?

Categories