I'm making a file explorer app using MVVM pattern in C# WPF. Right now I want to implement watcher events that are responsible for adding, removing and renaming items from treeview. I already have adding, and partially renaming (I think that in this case I have to combine deleting and adding). I'm struggling with deletion.
Deleted files are stil in the treeview. For example, Folder shouldn't exist anymore, because I deleted it.
App window
I would very much appreciate help from You. Here's a code I've written in class DirectoryInfoViewModel
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
namespace ViewModels {
public class DirectoryInfoViewModel : FileSystemInfoViewModel
{
public ObservableCollection<FileSystemInfoViewModel> Items { get; private set; } = new ObservableCollection<FileSystemInfoViewModel>();
public bool Open(string path)
{
bool result = false;
try
{
FileSystemWatcher Watcher = new FileSystemWatcher(path);
Watcher.Created += OnFileCreated;
Watcher.Renamed += OnFileRenamed;
Watcher.Deleted += OnFileDeleted;
//Watcher.Changed += OnFileChanged;
Watcher.Error += Watcher_Error;
Watcher.EnableRaisingEvents = true;
foreach (var dirName in Directory.GetDirectories(path))
{
var dirInfo = new DirectoryInfo(dirName);
DirectoryInfoViewModel itemViewModel = new DirectoryInfoViewModel
{
Model = dirInfo
};
itemViewModel.Open(dirName);
Items.Add(itemViewModel);
}
foreach (var fileName in Directory.GetFiles(path))
{
var fileInfo = new FileInfo(fileName);
FileInfoViewModel itemViewModel = new FileInfoViewModel();
itemViewModel.Model = fileInfo;
Items.Add(itemViewModel);
}
result = true;
}
catch (Exception ex)
{
Exception = ex;
}
return result;
}
public Exception Exception { get; private set; }
private static void Watcher_Error(object sender, ErrorEventArgs e) =>
System.Windows.MessageBox.Show(e.GetException().ToString());
public void OnFileCreated(object sender, FileSystemEventArgs e)
{
System.Windows.Application.Current.Dispatcher.Invoke(() => OnFileCreated(e));
}
private void OnFileCreated(FileSystemEventArgs e)
{
Debug.WriteLine("File Created: " + e.Name);
if (!Items.Any(x => x.Caption == e.Name))
{
var dirInfo = new DirectoryInfo(e.FullPath);
DirectoryInfoViewModel itemViewModel = new DirectoryInfoViewModel();
itemViewModel.Model = dirInfo;
Items.Add(itemViewModel);
}
}
public void OnFileDeleted(object sender, FileSystemEventArgs e)
{
System.Windows.Application.Current.Dispatcher.Invoke(() => OnFileDeleted(e));
}
private void OnFileDeleted(FileSystemEventArgs e)
{
Debug.WriteLine("File Deleted: " + e.Name);
if (Items.Any(x => x.Caption == e.Name))
{
var dirInfo = new DirectoryInfo(e.FullPath);
Debug.WriteLine("File path: " + e.FullPath);
DirectoryInfoViewModel itemViewModel = new DirectoryInfoViewModel();
itemViewModel.Model = dirInfo;
Items.Remove(itemViewModel);
}
}
public void OnFileRenamed(object sender, FileSystemEventArgs e)
{
System.Windows.Application.Current.Dispatcher.Invoke(() => OnFileRenamed(e));
}
private void OnFileRenamed(FileSystemEventArgs e)
{
Debug.WriteLine("File Renamed: " + e.Name);
OnFileDeleted(e);
OnFileCreated(e);
}
} }
In private void OnFileDeleted(FileSystemEventArgs e) you create a new DirectoryInfoViewModel and attempt to remove it from the Items collection. ObservableCollection<T>.Remove(T) removes item based on a reference equality check if T does not provide an alternative equality check.
So you attempt to remove an item from for you Items collection which is not in the collection. If you check the return value of Items.Remove(itemViewModel) you will see that it returns false as no item equal to itemViewModel was found in the collection (see Collection.Remove(T)).
This would fix the problem by finding the item you want to remove and then removing it.
private void OnFileDeleted(FileSystemEventArgs e)
{
if (Items.Any(x => x.Caption == e.Name))
{
var toDelete = Items.Single(x => x.Caption == e.Name);
Items.Remove(toDelete);
}
}
Related
I am writing a program which is supposed to detect when a USB serial device is plugged in and then log on to the new com port. The code below works wonderfully, but I have noticed in debugging the code and stepping through it that the event handler "DetectChange" fires twice. I'm not sure that this is normal, or an action of the debugger.
In any case, the code works, but I am new at event handling and I would like to make sure that I am not going to cause any issues as I add more code to actually read and write from the serial port.
(I got some of this code from stackoverflow, but I have misplaced my paper with names for attribution. If you see your code below, my heartfelt thanks.)
using System;
using System.IO.Ports;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Management;
using System.Threading;
namespace SerialTest
{
public partial class Form1 : Form
{
SerialMethods serialMethods = new SerialMethods();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
loadCmdBox();
}
private void CmdBoxPort_SelectedIndexChanged(object sender, EventArgs e)
{
handleComPort();
}
private void handleComPort()
{
// Set the right port for the selected item.
// The portname is based on the "COMx" part of the string (SelectedItem)
string item = CmdBoxPort.SelectedItem.ToString();
// Search for the expression "(COM" in the "selectedItem" string
if (item.Contains("(COM"))
{
// Get the index number where "(COM" starts in the string
int indexOfCom = item.IndexOf("(COM");
// Set PortName to COMx based on the expression in the "selectedItem" string
// It automatically gets the correct length of the COMx expression to make sure
// that also a COM10, COM11 and so on is working properly.
string PortName = item.Substring(indexOfCom + 1, item.Length - indexOfCom - 2);
if (serialMethods._serialPort.IsOpen)
{
serialMethods._serialPort.Close();
serialMethods.Connect(PortName);
label5.Text = "Active Port: " + PortName;
}
else
{
serialMethods.Connect(PortName);
label5.Text = PortName;
}
}
else
return;
}
private void loadCmdBox()
{
// Get all serial (COM)-ports you can see in the devicemanager
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\cimv2",
"SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
// Sort the items in the combobox
CmdBoxPort.Sorted = true;
// Add all available (COM)-ports to the combobox
foreach (System.Management.ManagementObject queryObj in searcher.Get().Cast<ManagementObject>())
{
CmdBoxPort.Items.Add(queryObj["Caption"]);
}
SerialPortService.PortsChanged += (sender1, changedArgs) => DetectChange(changedArgs.EventType);
label2.Text = "";
label3.Text = "";
label4.Text = "";
}
protected Task<Task> getSerPorts()
{
CmdBoxPort.Text = "";
CmdBoxPort.Update();
if (!String.IsNullOrEmpty(CmdBoxPort.Text))
{
handleComPort();
return Task.FromResult(Task.CompletedTask);
}
else
{
loadCmdBox();
return Task.FromResult(Task.CompletedTask);
}
}
private void ExitButton_Click(object sender, EventArgs e)
{
SerialPortService.CleanUp();
this.Close();
}
private void RefreshButton_Click(object sender, EventArgs e)
{
refresh();
}
protected Task<Task> refresh()
{
label2.Text = "";
label3.Text = "";
label4.Text = "";
CmdBoxPort.Items.Clear();
getSerPorts();
return Task.FromResult(Task.CompletedTask);
}
protected virtual void DetectChange(EventType changedArgs)
{
if (changedArgs == EventType.Insertion)
{
try
{
Task tr = (Task)Invoke(new Action( () => { getSerPorts(); }));
Task rr = (Task)Invoke(new Action(() => { refresh(); }));
}
catch (Exception ex) { MessageBox.Show("Exception at insertion invoke method " + ex, "Exception", MessageBoxButtons.OK); }
}
else if (changedArgs == EventType.Removal)
{
try
{
Task tr = (Task)Invoke(new Action( () => { getSerPorts(); }));
Task rr = (Task)Invoke(new Action(() => { refresh(); }));
}
catch (Exception ex) { MessageBox.Show("Exception at removal invoke method " + ex, "Exception", MessageBoxButtons.OK); }
}
return;
}
}
public static class SerialPortService
{
private static SerialPort _serialPort;
private static string[] _serialPorts;
private static ManagementEventWatcher arrival;
private static ManagementEventWatcher removal;
private static readonly SerialMethods SD = new SerialMethods();
static SerialPortService()
{
_serialPorts = SerialPort.GetPortNames();
MonitorDeviceChanges();
}
public static void CleanUp()
{
arrival.Stop();
removal.Stop();
}
public static event EventHandler<PortsChangedArgs> PortsChanged;
private static void MonitorDeviceChanges()
{
try
{
var deviceArrivalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
var deviceRemovalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
arrival = new ManagementEventWatcher(deviceArrivalQuery);
removal = new ManagementEventWatcher(deviceRemovalQuery);
arrival.EventArrived += (o, args) => RaisePortsChangedIfNecessary(EventType.Insertion);
removal.EventArrived += (sender, eventArgs) => RaisePortsChangedIfNecessary(EventType.Removal);
// Start listening for events
arrival.Start();
removal.Start();
}
catch (ManagementException err)
{
MessageBox.Show("Management exception = " + err, "Info", MessageBoxButtons.OK);
}
}
private static void RaisePortsChangedIfNecessary(EventType eventType)
{
lock (_serialPorts)
{
var availableSerialPorts = SerialPort.GetPortNames();
if (eventType == EventType.Insertion)
{
var added = availableSerialPorts.Except(_serialPorts).ToArray();
_serialPorts = availableSerialPorts;
PortsChanged.Raise(null, new PortsChangedArgs(eventType, added));
}
else if (eventType == EventType.Removal)
{
var removed = _serialPorts.Except(availableSerialPorts).ToArray();
_serialPorts = availableSerialPorts;
PortsChanged.Raise(null, new PortsChangedArgs(eventType, removed));
}
}
}
public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
handler?.Invoke(sender, args);
}
}
public enum EventType
{
Insertion,
Removal,
}
public class PortsChangedArgs : EventArgs
{
private readonly EventType _eventType;
private readonly string[] _serialPorts;
public PortsChangedArgs(EventType eventType, string[] serialPorts)
{
_eventType = eventType;
_serialPorts = serialPorts;
}
public string[] SerialPorts => _serialPorts;
public EventType EventType => _eventType;
}
}
Just took a short look at this. It seems like getSerPorts() will always execute loadCmdBox() (CmdBoxPort.Text = ""; ... if (!String.IsNullOrEmpty(CmdBoxPort.Text))) that will attach a new event handler (previous attached event handlers will not be removed by attaching a new one).
You should either remove the existing event handler befor attaching a new one or only attach the event handler once.
I have some files that are written to a folder.First there are 2 files written and after 10-20 minutes the next 2 files.
My question is:
Is there any possible way to tell the file system watcher
to wait until all 4 files are in the folder before executing my code?
According to #BugFinder 's suggestion I created something similar but didn't test. Hope it is useful:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace CustomFileWatcher
{
public class CustomFileWatcher : IDisposable
{
private FileSystemWatcher fileWatcher;
private IList<string> fileList;
private IList<string> createdFiles;
public event EventHandler FilesCreated;
protected void OnFilesCreated(EventArgs e)
{
var handler = FilesCreated;
if (handler != null)
handler(this, e);
}
public CustomFileWatcher(IList<string> waitForTheseFiles, string path)
{
fileList = waitForTheseFiles;
createdFiles = new List<string>();
fileWatcher = new FileSystemWatcher(path);
fileWatcher.Created += fileWatcher_Created;
}
void fileWatcher_Created(object sender, FileSystemEventArgs e)
{
foreach (var item in fileList)
{
if (fileList.Contains(e.Name))
{
if (!createdFiles.Contains(e.Name))
{
createdFiles.Add(e.Name);
}
}
}
if (createdFiles.SequenceEqual(fileList))
OnFilesCreated(new EventArgs());
}
public CustomFileWatcher(IList<string> waitForTheseFiles, string path, string filter)
{
fileList = waitForTheseFiles;
createdFiles = new List<string>();
fileWatcher = new FileSystemWatcher(path, filter);
fileWatcher.Created += fileWatcher_Created;
}
public void Dispose()
{
if (fileWatcher != null)
fileWatcher.Dispose();
}
}
}
Usage
class Program
{
static void Main(string[] args)
{
IList<string> waitForAllTheseFilesToBeCopied = new List<string>();
waitForAllTheseFilesToBeCopied.Add("File1.txt");
waitForAllTheseFilesToBeCopied.Add("File2.txt");
waitForAllTheseFilesToBeCopied.Add("File3.txt");
string watchPath = #"C:\OutputFolder\";
CustomFileWatcher customWatcher = new CustomFileWatcher(waitForAllTheseFilesToBeCopied, watchPath);
customWatcher.FilesCreated += customWatcher_FilesCreated;
}
static void customWatcher_FilesCreated(object sender, EventArgs e)
{
// All files created.
}
}
I'm writing a small WPF application in C# using Kinect and COMs to communicate to an arduino.
I have a combobox where the user can choose the port that he wants to use, I have a watcher on my COMs and everytime a device is Plugged/Unplugged I want to refresh my combobox.
My problem is that the calling to the function is in another class so I have a thread error
Here is the portion of code that doesn't work :
namespace Microsoft.Samples.Kinect.SkeletonBasics
{
using System.IO;
using System.IO.Ports;
using System;
using System.Management;
using System.Windows;
using System.Windows.Media;
using System.Collections.Generic;
using System.Windows.Controls;
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
public partial class MainWindow : Window
{
private WMIReceiveEvent receiveEvent = new WMIReceiveEvent();
internal static ComboBox comboBox; //Internal static variable so it can be used in static method
public MainWindow()
{
InitializeComponent();
}
private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
using (receiveEvent) {}
}
private void ComboBox_Loaded(object sender, RoutedEventArgs e)
{
comboBox = Com_ComboBox;
string[] ports = SerialPort.GetPortNames();
if (ports.Length == 0)
{
Default_Text.Content = "Aucun port détecté";
comboBox.IsHitTestVisible = false;
comboBox.Focusable = false;
}
else Default_Text.Content = "Arduino sur le port :";
comboBox.SelectedIndex = 0;
foreach (string port in ports)
{
comboBox.Items.Add(port);
}
}
internal static void Refresh_Coms() //I'm trying to call this function from the other class but I get a thread error
{
comboBox.Items.Clear();
ComboBoxItem Default_Text = (ComboBoxItem) comboBox.ItemContainerGenerator.ContainerFromIndex(0);
string[] ports = SerialPort.GetPortNames();
if (ports.Length == 0)
{
Default_Text.Content = "Aucun port détecté";
comboBox.IsHitTestVisible = false;
comboBox.Focusable = false;
comboBox.SelectedIndex = 0;
}
else Default_Text.Content = "Arduino sur le port :";
foreach (string port in ports)
{
comboBox.Items.Add(port);
}
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
public class WMIReceiveEvent : IDisposable
{
private ManagementEventWatcher watcherAttach;
private ManagementEventWatcher watcherDetach;
public WMIReceiveEvent()
{
try
{
watcherAttach = new ManagementEventWatcher();
watcherAttach.EventArrived += Attaching;
watcherAttach.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
watcherAttach.Start();
watcherDetach = new ManagementEventWatcher();
watcherDetach.EventArrived += Detaching;
watcherDetach.Query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3");
watcherDetach.Start();
return;
}
catch (ManagementException err)
{
MessageBox.Show("An error occurred while trying to receive an event: " + err.Message);
}
}
public void Dispose()
{
try
{
watcherAttach.Stop();
watcherDetach.Stop();
watcherAttach.Dispose();
watcherDetach.Dispose();
}
catch
{
MessageBox.Show("An error occurred while trying to close COM event Handler");
}
}
void Attaching(object sender, EventArrivedEventArgs e)
{
if (sender != watcherAttach) return;
Console.WriteLine("Attaching");
MainWindow.Refresh_Coms(); //I can call the function but the thread can't modify the ComboBox
}
void Detaching(object sender, EventArrivedEventArgs e)
{
if (sender != watcherDetach) return;
Console.WriteLine("Detaching");
MainWindow.Refresh_Coms();
}
~WMIReceiveEvent()
{
this.Dispose();
}
}
}
I'm a little new to C#, I've searched on the web but I can't find an easy solution for doing that, can somebody help me please ?
Add SynchronizationContext to Your WMIReceiveEvent class, like:
public class WMIReceiveEvent : IDisposable
{
private readonly SynchronizationContext _syncContext;
public WMIReceiveEvent(SynchronizationContext syncContext)
{
_cyncContext = syncContext;
}
}
and wrap of calling MainWindow.Refresh_Coms(); with Send method of SynchronizationContext:
_syncContext.Send(o => MainWindow.Refresh_Coms(), null);
And last thing is creating Your WMIReceiveEvent class:
private WMIReceiveEvent receiveEvent = new WMIReceiveEvent(SynchronizationContext.Current);
More about SynchronizationContext.
I'm creating an add in for Microsoft Excel that includes a ribbon tab. On this tab is a button with the following code:
public void setAccounts()
{
foreach (Excel.Worksheet displayWorksheet in Globals.ThisAddIn.Application.Worksheets)
{
displayWorksheet.Range[budget_cell].Value2 = "$" + Convert.ToString(budget);
displayWorksheet.Range[account_cell].Value2 = "$0.00";
displayWorksheet.Range[transaction_cell].Value2 = "Amount";
}
}
The button opens up a separate form where the user specifies budget_cell, account_cell, and transaction_cell. I then pass that data to the above code in SolutionName.ThisAddIn.cs (where SolutionName is the namespace of the solution). Strictly speaking, the code works. However, the data doesn't show up in the cells until the button is pressed a second time. Why is that? Is it because I'm retrieving the data from a different object in the solution?
Also, I've been trying to get this code and the aforementioned form to activate when the add in first starts up.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
frmStartup startup = new frmStartup();
startup.Show();
setAccounts();
}
I've been at this for a good twelve hours now, and I can't get it to work. What am I missing?
ThisAddIn.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
namespace AccountingAddIn
{
public partial class ThisAddIn
{
public static string budget_cell = "";
public static string account_cell = "";
public static string transaction_cell = "";
public static string date_cell = "";
public static string time_cell = "";
public static string description_cell = "";
public static bool date = false;
public static bool time = false;
public static bool description = false;
public static decimal budget = 0;
List<Account> accounts = new List<Account>();
public void budgetStartUp()
{
frmStartup startup = new frmStartup();
startup.Show();
setAccounts();
}
public void setAccounts()
{
foreach (Excel.Worksheet displayWorksheet in Globals.ThisAddIn.Application.Worksheets)
{
displayWorksheet.Range[budget_cell].Value2 = "$" + Convert.ToString(budget);
displayWorksheet.Range[account_cell].Value2 = "$0.00";
displayWorksheet.Range[transaction_cell].Value2 = "Amount";
if (date == true)
{
displayWorksheet.Range[date_cell].Value2 = "Date";
}
if (time == true)
{
displayWorksheet.Range[time_cell].Value2 = "Time";
}
if (description == true)
{
displayWorksheet.Range[description_cell].Value2 = "Description";
}
Account na = new Account(0, displayWorksheet);
accounts.Add(na);
}
}
protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return Globals.Factory.GetRibbonFactory().CreateRibbonManager(
new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { new MyRibbon() });
}
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
CreateRibbonExtensibilityObject();
budgetStartUp();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
}
}
frmStartup.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace AccountingAddIn
{
public partial class frmStartup : Form
{
public frmStartup()
{
InitializeComponent();
}
private void btnHelp_Click(object sender, EventArgs e)
{
MessageBox.Show("Please enter a starting amount for your budget and " +
"which cells will display the running total for your " +
"accounts." +
"\n\nNote: Leaving the budget blank will" +
" result in a starting budget of $0.00.");
}
private void btnOkay_Click(object sender, EventArgs e)
{
AccountingSeminar.ThisAddIn.budget += Convert.ToDecimal(txtStartingAmount.Text);
AccountingSeminar.ThisAddIn.budget_cell = txtBudget.Text;
AccountingSeminar.ThisAddIn.account_cell = txtAccount.Text;
AccountingSeminar.ThisAddIn.transaction_cell = txtTransaction.Text;
if (chkDate.Checked)
{
AccountingSeminar.ThisAddIn.date_cell = txtDate.Text;
AccountingSeminar.ThisAddIn.date = true;
}
if (chkTime.Checked)
{
AccountingSeminar.ThisAddIn.time_cell = txtTime.Text;
AccountingSeminar.ThisAddIn.time = true;
}
if (chkDescription.Checked)
{
AccountingSeminar.ThisAddIn.description_cell = txtDescription.Text;
AccountingSeminar.ThisAddIn.description = true;
}
Close();
}
}
}
I have tried without success to follow the code given here and on other forums. I just cannot get the event to fire.
The same control added manually to the form works fine...it raises the event and the parent form consumes it. So the control is capable of working, just not in the way I am (so far) trying to do it with Reflection.
I have a small DEMO of the web application available for download here:
http://ube.dev.campuswebstore.mobi/dloadfile.htm
Here is the code and I will comment where I am trying to link the event to the handler (the part which is not working):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Reflection;
namespace WebApplication2
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, System.EventArgs e)
{
TestRaiseEvent77.ButtonClickEvent += new ButtonWasClicked(TestRaiseEvent77_ButtonClickEvent);
string layout = "";
if (Request.QueryString["layout"] != null)
{
layout = Request.QueryString["layout"] as string;
}
else
{
layout = "default";
}
if (!Page.IsPostBack)
{
GlobalMethods.InitControlList();
LoadControls(layout);
AddControlsFromList();
WireControlEventsToHandlers();
}
else
{
AddControlsFromList();
WireControlEventsToHandlers();
}
}
void TestRaiseEvent77_ButtonClickEvent(string message)
{
}
private void AddControlsFromList()
{
sitemanagercontrolsdiv.Controls.Clear();
try
{
if (GlobalMethods.divlayoutgencontrols != null)
{
foreach (Control c in GlobalMethods.divlayoutgencontrols)
{
sitemanagercontrolsdiv.Controls.Add(c);
}
}
}
catch (Exception eee)
{
string a = eee.Message;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
//NOTES:
//The control collection cannot be modified during
//DataBind,
//Init,
//Load,
//PreRender or
//Unload phases.
private void WireControlEventsToHandlers()
{
foreach (Control c in sitemanagercontrolsdiv.Controls)
{
Type controlType = c.GetType();
BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public;
EventInfo[] myEvents = controlType.GetEvents(myBindingFlags);
for (int j = 0; j < myEvents.Count(); j++)
{
string eventName = myEvents.ElementAt(j).Name;
if (eventName == "ButtonClickedEvent")
{
MethodInfo handler = typeof(_Default).GetMethod("SomeHandler");
Delegate del = Delegate.CreateDelegate(myEvents.ElementAt(j).EventHandlerType, this, handler);
//////////////////////////////// WHATEVER THIS IS DOING IT IS NOT WORKING
myEvents.ElementAt(j).AddEventHandler(c, del);
}
}
c.Visible = true;
string tempGUID = Guid.NewGuid().ToString();
c.ID = "TestRaiseEvent" + tempGUID + "1";
}
}
private void LoadControls(string layout)
{
Control c = LoadControl("~/TestRaiseEvent.ascx");
GlobalMethods.divlayoutgencontrols.Add(c);
}
////////////////// I AM TRYING TO LINK THE EVENT TO THIS HANDLER:
public void SomeHandler(string message)
{
// do something
}
}
}
My brother-in-law gave me the answer last night. Just a few minor changes having to deal with the ID of the control.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Reflection;
namespace WebApplication2
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_PreInit(object sender, System.EventArgs e)
{
string layout = "";
if (Request.QueryString["layout"] != null)
{
layout = Request.QueryString["layout"] as string;
}
else
{
layout = "default";
}
//if (!Page.IsPostBack) {
GlobalMethods.InitControlList();
LoadControls(layout);
//}
}
private void AddControlsFromList()
{
sitemanagercontrolsdiv.Controls.Clear();
try
{
if (GlobalMethods.divlayoutgencontrols != null)
{
foreach (Control c in GlobalMethods.divlayoutgencontrols)
{
sitemanagercontrolsdiv.Controls.Add(c);
}
}
}
catch (Exception eee)
{
string a = eee.Message;
}
}
protected void Page_Load(object sender, EventArgs e)
{
AddControlsFromList();
}
//The control collection cannot be modified during
//DataBind,
//Init,
//Load,
//PreRender or
//Unload phases.
protected void Page_LoadComplete(object sender, EventArgs e)
{
//AddControlsFromList();
}
private void LoadControls(string layout)
{
Control c = LoadControl("~/TestRaiseEvent.ascx");
Type controlType = c.GetType();
BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public;
EventInfo[] myEvents = controlType.GetEvents(myBindingFlags);
for (int j = 0; j < myEvents.Count(); j++)
{
string eventName = myEvents.ElementAt(j).Name;
if (eventName == "ButtonClickEvent")
{
MethodInfo handler = typeof(_Default).GetMethod("SomeHandler");
Delegate del = Delegate.CreateDelegate(myEvents.ElementAt(j).EventHandlerType, this, handler);
myEvents.ElementAt(j).AddEventHandler(c, del);
}
}
c.Visible = true;
//string tempGUID = Guid.NewGuid().ToString();
//c.ID = "TestRaiseEvent" + tempGUID + "1";
c.ID = "TestRaiseEvent1";
GlobalMethods.divlayoutgencontrols.Add(c);
}
public void SomeHandler(string message)
{
// do something
}
}
}