I want to rebuild the "look & feel" of MessageBox.Show() of WinForms applications.
With "look & feel" I mean to JUST CALL the MessageBox.Show() command with the logic of my already implemented ShowMessage method.
My current codebehind:
public partial class Testpage : System.Web.UI.Page
{
public enum MessageBoxIcon { Information, Error, Warning }
protected void Page_Load(object sender, EventArgs e)
{
ShowMessage("Testmessage", MessageBoxIcon.Error, ex);
}
private void ShowMessage(string title, string message, MessageBoxIcon type, Exception ex)
{
if (type == MessageBoxIcon.Information)
{
pnlMsgBox.CssClass = "MessageBoxInformation";
imgMsgBox.ImageUrl = "Resources/img/icon/MessageBoxIcon.Information.png";
}
else if (type == MessageBoxIcon.Warning)
{
pnlMsgBox.CssClass = "MessageBoxWarning";
imgMsgBox.ImageUrl = "Resources/img/icon/MessageBoxIcon.Warning.png";
}
else if (type == MessageBoxIcon.Error)
{
pnlMsgBox.CssClass = "MessageBoxError";
imgMsgBox.ImageUrl = "Resources/img/icon/MessageBoxIcon.Error.png";
}
else
throw new NotImplementedException();
lblMsgBox.Text = "<span style=\"font-size: large;\">" + title + "</span><br /><br />" + message;
#if (DEBUG)
if (ex != null)
lblMsgBox.Text += "<br /><br /><b>Debug information:</b> " + ex.Message;
#endif
pnlMsgBox.Visible = true;
updPnl.Update();
}
}
I'd like to call something like this:
protected void Page_Load(object sender, EventArgs e)
{
MessageBox.Show("Testmessage", MessageBoxIcon.Error, ex);
}
But
public static class MessageBox : Testpage
{
public static void Show(string message)
{
// do stuff with the page controls.
}
}
doesn't work as you all know, because Testpage isn't static.
Does anybody have some suggestions for me?
Reading the comments to the previous answer, I think next:
Its difficult to get access to current page context from the separated static class. So then, i recomendate do next:
Define next interface:
public interface IMessageBoxContainer
{
UpdatePanel UpdatePanel { get; }
Label Label { get; }
}
and implement him by your page as:
public partial class _Default : System.Web.UI.Page, IMessageBoxContainer
{
protected void Page_Load(object sender, EventArgs e)
{
}
public UpdatePanel UpdatePanel
{
get { return updatePanel1; }
}
public Label Label
{
get { return label1; }
}
}
This steps provide you to get access to your page from anywhere. After that implement you MessageBox NON-static class:
public class MessageBox
{
private IMessageBoxContainer container = null;
public MessageBox(IMessageBoxContainer _container)
{
container = _container;
}
public void Show(string message)
{
container.Label.Text = message;
container.UpdatePanel.Update();
}
}
Why non-static? Becouse if you do container field as static and set him value anywhere in page (for example in Page_Load), when another page will load - your container property will reset. But without this field, that pointer to your current page, you cant get access to your specefied controls.
After that you can use your class like that:
protected void Button1_Click(object sender, EventArgs e)
{
var box = new MessageBox(this);
box.ShowMessage("hello world");
}
So, you get separated implementation logic of your MessageBox and simple using him, yes? But unfurtunently, its non-static.
Try like this:
public static class MessageBox
{
public static void Show(string message)
{
HttpContext.Current.Response.Write(string.Format("<script>alert('{0}');</script>", message));
}
}
Of course, you will need to implement your own correct JavaScript to display you MessageBox on client-side. But I thing – you approach is wrong. For you method programming try to look in ASP.NET MVC, becouse classic ASP.NET do not fully support JavaScript coding.
Related
Hi I'm trying to make a single .html page that displays out the readings of my Raspberry Pi in Real-Time.
The Data is being sent over which triggers the Delegate.
However, the function that the Delegate triggers isn't able to interact with any Control in my ASP.Net Page.
Here's how my code looks like:
public partial class newIndex : System.Web.UI.Page
{
DataComms dataComms;
public void commsDataReceive(string strData)
{
// This line is able to successfully print out the strData
System.Diagnostics.Debug.WriteLine(strData);
// This line doesn't throw an error but doesn't work
Label1.Text = strData;
}
private void InitComms()
{
dataComms = new DataComms();
dataComms.dataReceiveEvent += new DataComms.DataReceivedDelegate(commsDataReceive);
}
protected void Page_Load(object sender, EventArgs e)
{
InitComms();
}
}
My theory is that after the Page loads I'm unable to make any changes to it dynamically?? So I can solve this using an UpdatePanel Right?
Well I tried that too and it didn't work also as I had to call UpdatePanel1.Update() which is accessing the control UpdatePanel.
If anyone could help I'll be so thankful!
Server pages do not work in this way. Most likely page is already sent to browser by the time commsDataReceive is fired. I guess you have only one "client" to show this information so you can make dataComms as static and update code to follow. This is certainly not the best solution but should work for your requirement
public partial class newIndex : System.Web.UI.Page
{
static DataComms dataComms;
static string lastData="";
public void commsDataReceive(string strData)
{
// This line is able to successfully print out the strData
System.Diagnostics.Debug.WriteLine(strData);
// This line doesn't throw an error but doesn't work
lastData = strData;
}
protected void Page_Load(object sender, EventArgs e)
{
if (dataComms != null)
{
dataComms = new DataComms();
dataComms.dataReceiveEvent += new DataComms.DataReceivedDelegate(commsDataReceive);
}
Label1.Text = lastData;
}
}
first of all, this may be stupid/dumb question but anyway, this is not a problem, basically im searching for the best proper way to show a result from a class to the main window.
now i will show you what i need, and then how i would solved this with my current knowledge, knowing that its incorrect way,
so on button click i do this:
private void btnSend_Click(object sender, RoutedEventArgs e)
{
new Notification().DoNotify(txtMessage.Text);
}
the classes definitions are:
public class Notification
{
private IMessenger _iMessenger;
public Notification()
{
_iMessenger = new Email();
}
public void DoNotify(string Message)
{
_iMessenger.SendMessage(Message);
}
}
interface IMessenger
{
void SendMessage(string Message);
}
public class SMS : IMessenger
{
public void SendMessage(string Message)
{
// i want code that will print this message variable to the txtSMS textbox.
}
}
public class Email : IMessenger
{
public void SendMessage(string Message)
{
// i want code that will print this message variable to the txtEmail textbox.
}
}
now how to update the main window GUI from these classes?,
one solution that i would use is, add new tempclass with the mainwindow object inside, and then access it,
public class TempClass
{
public static MainWindow Main;
}
in main window constructor:
public MainWindow()
{
InitializeComponent();
TempClass.Main = this;
}
and the sms/email classes:
public class Email : IMessenger
{
public void SendMessage(string Message)
{
TempClass.Main.txtEmail.Text = Message;
}
}
public class SMS : IMessenger
{
public void SendMessage(string Message)
{
TempClass.Main.txtSMS.Text = Message;
}
}
now this works, but there just has to be a better way... what do you think and sorry for long post... ://
is there any principle or design pattern about this ?
A static property is not recommended when you might have two or more instances of your application. You can define a method in MainWindow:
internal void SetMessage(string Message)
{
Dispatcher.BeginInvoke(new Action(() => {txtSMS.Text = Message;}));
}
and send the instance of your MainWindow to other classes, whether by a specific constructor
MainWindow parentWindow;
void btnSend_Click(object sender, RoutedEventArgs e)
{
if (parentWindow != null)
_parentWindow.SetMessage(txtMessage.Text);
}
or by defining a DependencyProperty and use Binding.
You can also use Events, however, I prefer the preceding.
As the title says, I need to pass a list of hashtables from a regular class to a form class to be rendered in a DataGridView. What I've got so far is this:
namespace somenamespace
{
class aldeloUpdater
{
private static string client = "chanchitos";
private static string establishment = "c1";
static void Main()
{
try
{
var guiForm = new GuiForm(); // Instantiating the Form-derived class.
string deliveriesListResp = getOrders();
Processing...
foreach (...)
{
if ((bool)DBresponse["status"])
{
guiForm.dataGridViewProducts = (List<Hashtable>)DBresponse["deliveriesSaved"]; // Passing the data to the DataGridView.
foreach (Hashtable delivery in (List<Hashtable>)DBresponse["deliveriesSaved"])
{
string updateDeliveryResponse = updatePedidoInDomicilios(delivery["domiciliosOrderId"].ToString(), 2, DBresponse["errmsg"].ToString());
}
}
else
{
Processing...
}
}
guiForm.ShowDialog(); // Showing the form.
More processing...
}
catch (Exception e)
{
Console.WriteLine("Exception details: " + e.ToString());
Console.ReadLine();
}
}
More methods...
}
Now the Form class looks like this:
namespace somenamespace
{
public partial class GuiForm : Form
{
public List<Hashtable> dataGridViewProducts; // Variable used to store the data to be rendered by the DataGridView.
public GuiForm()
{
InitializeComponent();
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void GuiForm_Load(object sender, EventArgs e)
{
int index = 0;
foreach (Hashtable product in dataGridViewProducts)
{
dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[0].Value = product["productName"];
dataGridView1.Rows[index].Cells[1].Value = product["userName"];
dataGridView1.Rows[index].Cells[2].Value = product["dateAndTime"];
dataGridView1.Rows[index].Cells[3].Value = product["domiciliosOrderId"];
index++;
}
}
Some more methods.
}
}
For now this code works just fine and the data is shown in the DataGridView, nonetheless I feel like there must be a better way to achieve this goal, it's just that I'm new to C#. I will appreciate suggestions and even more a code sketch of how you would do this in a better way.
Thanks.
I'm having an odd intermittent issue that I can't seem to reproduce consistently.
I have a custom NLog target called NotifyTarget, shown below:
internal delegate void NotifyTargetEventArgs(string message);
[Target("NotifyTarget")]
internal class NotifyTarget : TargetWithLayout
{
public event NotifyTargetEventArgs Notify;
private List<string> _logs = new List<string>();
public IList<string> Logs
{
get
{
return new ReadOnlyCollection<string>(_logs);
}
}
protected override void Write(LogEventInfo logEvent)
{
string message = Layout.Render(logEvent).TrimEnd();
_logs.Add(message);
OnNotify(message);
}
protected void OnNotify(string message)
{
if (Notify != null)
Notify(message);
}
}
I have an application with a child form called ErrorConsole that attaches to NotifyTarget.Notify:
public partial class ErrorConsole : Form
{
static NotifyTarget target;
static ErrorConsole()
{
target = LogManager.Configuration.FindTargetByName<NotifyTarget>("notify");
}
public ErrorConsole()
{
InitializeComponent();
}
private void ErrorConsole_Load(object sender, EventArgs e)
{
LoadLogs();
target.Notify += Log;
}
private void LoadLogs()
{
errorBox.AppendText(string.Join(Environment.NewLine + Environment.NewLine, target.Logs));
ScrollToLast();
}
private void Log(string message)
{
errorBox.Invoke((MethodInvoker)(() =>
{
string prefix = errorBox.Text == string.Empty ? "" : Environment.NewLine + Environment.NewLine;
errorBox.AppendText(prefix + message);
ScrollToLast();
}));
}
private void ScrollToLast()
{
errorBox.ScrollToCaret();
}
private void ErrorConsole_FormClosing(object sender, FormClosingEventArgs e)
{
target.Notify -= Log;
}
}
The ErrorConsole is loaded from a parent form (let's call it MainForm) after clicking a menu:
public partial class MainForm : Form
{
private ErrorConsole console;
// ...
private void errorConsoleMenu_Click(object sender, EventArgs e)
{
if (console == null || console.IsDisposed == true)
{
console = new ErrorConsole();
}
console.Show();
}
}
Whenever I do encounter this issue, I can set a breakpoint after target.Notify += Log; and inspect target.Notify with the debugger to verify that the Log method is indeed being registered:
However, if I put a breakpoint on if (Notify != null) and inspect Notify after continuing execution and triggering a log event, it appears to have been changed to null at some point:
When the application enters this "bad state", it persists for the whole session -- closing the form and trying again continues to fail, but restarting the application usually puts it back into a "good state".
What could be the cause of this behaviour?
You might have a rogue conditional breakpoint.
If you have one where you're testing for null, but the condition is
Notify = null
instead of
Notify == null
Then the breakpoint would be setting Notify to null rather than evaluating its value.
In one of my previous questions I explained about a form class that contain form field objects to save data in a user profile object (using profile provider).
The code is here bellow. Basically what I would like to accomplish is to pass as a parameter to my form field objects the field of the Profile object that they should interact in order to save the data later on.
You can see that in the following line:
//LastNameFormLine is an control that was added to my form page.
//The ProfileField parameter stores the field of the UserProfile object that is being manipulated by this control
LastNameFormLine.ProfileField = "UserProfile.LastName";
I was reading about reflection to be able to save this value in the UserProfileVisitor class, but I came across this concept of delegate in C# which I am not sure yet if I fully grasp.
Is it possible to delegate the ProfileField to a property on my UserProfile class? Or should I forget about it and go with reflection?
What would you suggest?
public partial class UserProfileForm : CustomIntranetWebappUserControl
{
protected override void OnInit(EventArgs e)
{
//AutoEventWireup is set to false
Load += Page_Load;
CancelLinkButton.Click += CancelButtonClickEvent;
SaveLinkButton.Click += SaveButtonClickEvent;
base.OnInit(e);
}
private void SaveButtonClickEvent(object sender, EventArgs e)
{
VisitFormFields();
}
private void VisitFormFields()
{
var userProfileVisitor = new UserProfileVisitor();
foreach (var control in Controls)
{
if (control is FormFieldUserControl)
{
var formField = (FormFieldUserControl) control;
formField.Visit(userProfileVisitor);
}
}
userProfileVisitor.Save();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindText();
}
}
private void BindText()
{
LastNameFormLine.LabelText = string.Format("{0}:", HomePage.Localize("Last Name"));
LastNameFormLine.InputValue = UserProfile.LastName;
LastNameFormLine.IsMandatoryField = true;
LastNameFormLine.IsMultilineField = false;
LastNameFormLine.ProfileField = "UserProfile.LastName";
//... the rest of this method is exactly like the 4 lines above.
}
}
public abstract class FormFieldUserControl : CustomIntranetWebappUserControl
{
public string ProfileField { get; set; }
public abstract void Visit(UserProfileVisitor userProfileVisitor);
}
public partial class FormLineTextBox : FormFieldUserControl
{
//... irrelevant code removed...
public override void Visit(UserProfileVisitor userProfileVisitor)
{
if (userProfileVisitor == null)
{
Log.Error("UserProfileVisitor not defined for the field: " + ProfileField);
return;
}
userProfileVisitor.Visit(this);
}
}
public class UserProfileVisitor
{
public void Visit(FormLineTextBox formLine)
{
// The value of formLine.ProfileField is null!!!
Log.Debug(string.Format("Saving form field type {1} with profile field [{0}] and value {2}", formLine.ProfileField, formLine.GetType().Name, formLine.InputValue));
}
// ... removing irrelevant code...
public void Save()
{
Log.Debug("Triggering the save operation...");
}
}
Delegates are not for properties. However, Reflection is slow, may have issues with code security and it's not typesafe and may lead to runtime instead of compile-time problems on naming errors due to the late-bound nature.
That said, you may want to use getter and/or setter methods and use delegates on those.