I have a BaseControl, of which almost all my controls inherit from.
Right now I am working on security and I want to block users from viewing certain items if they do not have access.
I am able to do so on the Loaded event of the base control, but this is too late, this meanse the whole control gets rendered, and then replaced. I would like to replace it before it renders
here is an example of my code:
public class BaseControl : UserControl
{
public BaseControl()
{
this.Loaded +=BaseControl_Loaded;
}
private void BaseControl_Loaded(object sender, RoutedEventArgs e)
{
if (!userHasAccess)
{
this.Content = new AccessDenied();
}
}
}
The above code works perfectly, but a bit too late, Is there a way that I can do this before the Loaded event?
You want to override the OnInitialized where the constructor and properties are being set up before the Render happens.
protected override void OnInitialized(EventArgs e)
{
if (!userHasAccess)
{
this.Content = new AccessDenied();
}
base.OnInitialized(e);
}
More information can be found here.
Check out following sites:
http://msdn.microsoft.com/en-us/library/ms745025(v=vs.110).aspx
Also check object lifetime events that is what you asking for.
http://msdn.microsoft.com/en-us/library/ms754221(v=vs.110).aspx
Related
I am trying to update picture box image inside "form1" from another cs file
my code inside test.cs
slot_13.modifier = public;
and inside form1 i wrote this also
CheckForIllegalCrossThreadCalls = false;
test.cs
inventory_Viewer.viewer x = new inventory_Viewer.viewer();
x.slot_13.Image = Image.FromFile(#"C:\Users\Axmed\Google Drive\C# Source Codes\inventory Viewer\inventory Viewer\bin\Release\icon\icon_default.png");
But it doesn't work
If i used this line inside "form1"
x.slot_13.Image = Image.FromFile(#"C:\Users\Axmed\Google Drive\C# Source Codes\inventory Viewer\inventory Viewer\bin\Release\icon\icon_default.png");
image gets changed
Your code misses a lot of context, so I'm going to do a few assumptions. Given a MainForm that shows the InventoryViewerForm and also wants to change the image on the InventoryViewerForm, you could hold a reference to the second form like this:
// Your inventory_Viewer.viewer
public partial class InventoryViewerForm
{
public InventoryViewerForm()
{
}
}
// The form from which to show the viewer.
public partial class MainForm
{
private readonly InventoryViewerForm _inventoryViewerForm;
public MainForm()
{
_inventoryViewerForm = new InventoryViewerForm();
}
private void ShowInventoryViewerButton_Click(object sender, EventArgs e)
{
_inventoryViewerForm.Show();
}
private void ChangeImageButton_Click(object sender, EventArgs e)
{
// Dispose the previously loaded image.
if (_inventoryViewerForm.Image != null)
{
_inventoryViewerForm.Image.Dispose();
}
_inventoryViewerForm.Image = Image.FromFile("NewImage.png");
}
}
But this is bad design altogether. You don't want to tightly couple your forms like this, and you want to leverage the data binding of WinForms and the events of .NET for this. In order to properly implement that, you'll need to show more code.
I just want to ensure that the code below will not be causing the ChildWindow Login in this case to never be collected by the GC. Just to clarify the sample this comes from a silverlight page that is inherited by all other pages therefore the virtual void pageloaded method.
public class MyPage : Page
{
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
_user = App.AuthenticatedUser;
if (!_user.IsValid)
{
Login loginWindow = new Login(_user);
loginWindow.Closed += new EventHandler(PageLoaded);
loginWindow.Show();
}
else
PageLoaded(this, e);
}
//to be overridden by the pages extending this page control
protected virtual void PageLoaded(object sender, EventArgs e) { }
Thanks for your help.
This is fine. The loginWindows's Close event knows of your handler, not the other way around, so the form will not have any ties preventing the GC from picking it up.
Unregistering event handlers becomes important if the object your event is defined on will persist in the application for a long time (and you do not want the event handler association to persist for the same duration).
I am working on my first C# and .NET project that uses WinForms, as WPF would be an overkill for our purposes. I created a so-called ButtonMenu that comprises of all menu points, which are buttons. This class is derived from the Windows class Control.
One of the buttons of the ButtonMenu is the "Culture" button that, when pressed in this single-touch application, should change the language of all the forms the application has.
Originally, the ButtonMenu was just a kind of overlay class that accessed the controls of the BaseForm and contained methods. The BaseForm was holding the buttons inside a GroupBox of its own. Later, I run into problems with this kind of design and decided to make a separate control out of it.
My question
How can I create an event (or something similar to it) that can be caught by BaseForm, where the ButtonMenu is placed? The BaseForm can currently not react on this event and cannot change the language of all its own controls, such as text fields and buttons.
Thank you for your help!
What I have tried till now is shown below. Unfortunately, I cannot reach the marked line.
public class BaseForm : Form
{
[…]
protected static ButtonMenu m_ButtonMenu = null;
protected override void OnResize(EventArgs e)
{
[…]
m_ButtonMenu = ButtonMenu.GetInstance(m_CurrentCulture, Size);
m_ButtonMenu.Visible = true;
[…]
}
public override void UpdateWidgets()
{
[…]
try
{
[…]
// Translate button menu into current language:
m_ButtonMenu.AdaptButtons(m_CurrentCulture);
}
catch (ArgumentOutOfRangeException aaore)
{
[…]
[…]
}
protected void InitializeWidgets()
{
{
string strMethod = Name + ":InitializeWidgets(): ";
m_ButtonMenu = ButtonMenu.GetInstance(m_CurrentCulture, Size);
SuspendLayout();
Controls.Add(m_ButtonMenu);
m_ButtonMenu.Top = Height - m_ButtonMenu.Height;
ResumeLayout();
[…]
m_ButtonMenu.Click += new System.EventHandler(this.ButtonMenu_CultureClick);
}
private void ButtonMenu_CultureClick(object sender, EventArgs eas)
{
int iSelection = listViewMessages.SelectedIndices[0]; // <<<<< NEVER REACHED!
[…]
}
Just define an event in your class.
Whenever you want it to fire, call it.
// field
event EventHandler somethingHappened;
// in a method:
var threadSafeCopy = somethingHappened;
if(threadSafeCopy != null)
{
threadSafeCopy(this, e);
}
Where e is an instance of EventArgs or a sub type of EventArgs.
I have a listBox that I would like to carry out a method when its loaded up, although I can't use the Form "On_Load" trigger, since the ListBox is within a TabControl.
Is there a way of getting a method to execute when the object initializes?
The closest analog for controls is the HandleCreated event. This will fire when the underlying control handle is created, which is slightly before the Loaded event of the parent window would fire.
As #SLaks stated, you could put in your class's constructor. However, if what you want to prepare relies on other elements in the form, you can add to the event handler queue at the end of a form loading, but before its actually presented to the user.
In the constructor code of your form (not the designer code), add to the load event, then add your own custom function
public partial class frmYourForm : Form
{
public frmYourForm()
{
Load += YourPreparationHandler;
}
private void YourPreparationHandler(object sender, EventArgs e)
{
// Do you code to prepare list, combos, query, bind, whatever
}
}
Have the same problem, the previous answers apply well, for a single case.
But, I require to do something in most controls, in several forms, in an app.
Solved by using an interface:
interface IOnLoad
{
void OnLoad();
}
And added to descendant control:
public partial class MyButton : Button, IOnLoad
{
void OnLoad() { // call "OnLoadDelegate" }
}
public partial class MyForm : Form
{
public void MyForm_Load(...) {
foreach(Control eachControl in Controls) {
if (eachControl is IOnLoad) {
IOnLoad eachOnLoadControl = (IOnLoad)eachControl;
eachOnLoadControl.OnLoad();
}
} // foreach
}
} // class
Its more complex, but it suit my requirements.
You can use OnHandleCreated(EventArgs e). However, it triggers during design time too. You can override it too.
Can you use the HandleCreated event?
You can just put your code in the constructor.
You usually don't need to wait for any initialization.
I have a control that handles commenting. In this control, I have set a delegate event handler for sending an email.
I then have various types of controls, e.g. blog, articles etc, each of which may or may not have the commenting control added (which is done dynamically with me not knowing the id's), i.e. the commenting control is added outside this control. Each of these controls handles it's emailing differently(hence the event).
What I'm trying to determine, is how to assign the event in the parent control. At the moment, I'm having to recursively search through all the controls on the page until I find the comment control, and set it that way. Example below explains:
COMMENTING CONTROL
public delegate void Commenting_OnSendEmail();
public partial class Commenting : UserControl
{
public Commenting_OnSendEmail OnComment_SendEmail();
private void Page_Load(object sender, EventArgs e)
{
if(OnComment_SendEmail != null)
{
OnComment_SendEmail();
}
}
}
PARENT CONTROL
public partial class Blog : UserControl
{
private void Page_Load(object sender, EventArgs e)
{
Commenting comControl = (Commenting)this.FindControl<Commenting>(this);
if(comControl != null)
{
comCtrol.OnComment_SendEmail += new Commenting_OnSendMail(Blog_Comment_OnSendEmail);
}
}
}
Is there an easier way?
EDIT:
The reason I ask is that if I search from this.Page as the initial control, I am worried about time taken to search down the control tree to find it. Each different type of page would be different in how many control it would have. On some testing, it returns back quite quickly the result.
You could override the AddedControl event of your Blog class and check if the added control is instance of type Commenting. Something like:
public partial class Blog : UserControl {
protected override void AddedControl(Control control, int index) {
base.AddedControl(control, index);
Commenting commentingControl = control as Commenting;
if (commentingControl == null) return;
commentingControl.OnComment_SendEmail += new Commenting_OnSendMail(Blog_Comment_OnSendEmail);
}
}
Of course, you can put this code on a base class of all your "commentable" user controls and have an abstract method to actually handle the event.
Just one thing: the AddControl event happens AFTER the Page_Load, so be careful.
Cheers,
André