I have a label within a user control:
<asp:Label runat="server" ID="lblRemainingPlacesMessage" Visible="false" />
I want to setup its visibility to true:
protected void Page_Load(object sender, EventArgs e) {
lblRemainingPlacesMessage.Visible = true;
}
However, the label is still hidden.
What's is puzzling me, is that the property can't be changed, even in the immediate window, or the debugger local watch:
(immediate window)
lblRemainingPlacesMessage.Visible
false
lblRemainingPlacesMessage.Visible = true
true
lblRemainingPlacesMessage.Visible
false
What can explain that my Visible property can't be changed?
I have no exception. Just a NOOP like operation...
My app has the viewstate enabled. Most of all, I have other label in the page, that works perfectly!
Don't know if its matter, but I dynamically instantiate my user control within my owner page using:
protected override void CreateChildControls()
{
m_VisualControl = (MyUserControl)Page.LoadControl(_ascxPath);
Controls.Add(m_VisualControl);
}
The app uses ASP.Net WebForms with .net 3.5 SP1, and I use Visual Studio 2012 Premium.
Yuriy Galanter's comment put me on the right track.
Simply, my immediate parent was not visible. And I suppose the visible property of a control combines the control ancestors visibility.
Sometimes simple problem have simple resolution :)
1) You should create any dynamic UserControl at OnInit or you will not be able to use ViewState:
2) Expose the label property that you wan't to change as property of the UserControl
public bool HiddeMyLabel
{
set { lblRemainingPlacesMessage.Visible = value; }
get { lblRemainingPlacesMessage.Visible; }
}
3) You should ever use OnPreRender from the page to change any control property.
protected override void OnPreRender(EventArgs e)
{
MyUserControl.HiddeMyLabel = false;
}
4) If you still having issues, remove the hidden attribute manually:
public bool HiddeMyLabel
{
set
{
if(value)
lblRemainingPlacesMessage.Attributes.Add("style", "display:none");
else
lblRemainingPlacesMessage.Attributes.Add("style", "display:block");
}
}
Related
I'm am a little bit stuck in the ASP.Net's page lifecycle. This is my first ASP.Net project after many years of doing React so I might be missing something;)
Simplified code:
protected void Page_Load(object sender, EventArgs e)
{
BuildView();
}
private void BuildView()
{
switch (pageViewMode.Value)
{
case "Overview": BuildOverview(); break;
case "Runs": BuildRunsOverview(); break;
}
}
private void BuildOverview()
{
var tilesContainer = new TilesContainer();
tilesContainer.OnTileClicked += (InfoTile targetTile) =>
{
pageViewMode.Value = targetTile.Value;
BuildView();
};
rootElement.Controls.Add(tilesContainer);
}
The problem is that the "OnTileClicked" event works only on the first load and not after the postback. I believe it has something to do with the page lifecycle and registering the events after the Control events ( https://learn.microsoft.com/en-us/previous-versions/aspnet/ms178472(v=vs.100)?redirectedfrom=MSDN ).
If it is really the case, how do I then dynamically build pages from the code behind? Should I really create all the controls ( BuildOverview() and BuildRunsOverview()) and then conditionally show or hide them?
'Should I really create all the controls ( BuildOverview() and BuildRunsOverview()) and then conditionally show or hide them?'
Answer is: yes.
You don't dynamically build pages from code behind - at least its not that well supported in asp.net pages.
In your case you need the TilesContainer on every postback and attach the event handler to it, else the event won't be called. So it would be easier to put all your controls in the markup (.aspx) and just set them to Visible = false/true depending on your code. Controls you set to Visible = false won't be rendered on the client side, so at least no overhead there.
If you use custom-controls (I assume your TilesContainer is a custom-control), then you need to implement the Visible-property the right way, e.g. if your TilesContainers main control is a Panel, override Visible and set the value there:
public override bool Visible
{
get { return base.Visible; }
// set all neccessary controls visibility here
set { this.pnlMain.Visible = base.Visible = value; }
}
I'm trying to create a custom container as UserControl.
My Goal: I want to be able to drag controls inside the designer and handle incoming controls inside the code of my usercontrol.
Example: I place my container somewhere and then add a button. In this momemt I want my usercontrol to automatically adjust the width and position of this button. Thats the point where Im stuck.
My code:
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ContactList : UserControl
{
public ContactList()
{
InitializeComponent();
}
private void ContactList_ControlAdded(object sender, ControlEventArgs e)
{
e.Control.Width = 200; // Nothing happens
e.Control.Height = 100; // Nothing happens
MessageBox.Show("Test"); // Firing when adding a control
}
}
The MessageBox is working well. The set width and height is ignored.
The question is just "why?".
EDIT
I've just noticed, when placing the button and recompiling with F6 the button gets resized to 200x100. Why isnt this working when placing?
I mean... the FlowLayoutPanel handles added controls right when you place it. Thats the exact behaviour im looking for.
Using OnControlAdded
To fix your code, when you drop a control on container and you want to set some properties in OnControlAdded you should set properties using BeginInvoke, this way the size of control will change but the size handles don't update. Then to update the designer, you should notify the designer about changing size of the control, using IComponentChangeService.OnComponentChanged.
Following code executes only when you add a control to the container. After that, it respects to the size which you set for the control using size grab handles. It's suitable for initialization at design-time.
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
if (this.IsHandleCreated)
{
base.BeginInvoke(new Action(() =>
{
e.Control.Size = new Size(100, 100);
var svc = this.GetService(typeof(IComponentChangeService))
as IComponentChangeService;
if (svc != null)
svc.OnComponentChanged(e.Control,
TypeDescriptor.GetProperties(e.Control)["Size"], null, null);
}));
}
}
Good day!
I'm writing a .vsix to replace old controls to new ones. I have designerHost which is the current designer instance. Then I start converting like this:
foreach (OldCombo oldCmbx in OldCmbxs())
{
...
NewCombo newCmbx = designerHost.CreateComponent(NewComboType, oldcmbx.Name) as NewCmbx;
...
newCmbx.Visible = oldCmbx.Visible;
...
designerHost.DestroyComponent(oldCmbx);
}
The thing is -oldCmbx is always Visible=true, no matter how it's written in the designer.cs file. I'm always creating Visible=true newCmbx's. If I force newCmbx to be Visible=false, then designer doesn't show newCmbx after the conversion, but the visible property is still true, so Visible property is definitely not what I'm searching for. So how can I force newCmbx's to be Visible=false in designer.cs?
After digging through .NET source code I've found that ControlDesigner is shadowing Visible property of the Control, so what is going to be serialized/deserialized in InitializeComponent is far related from actual Visible property of Control.
Designer.Visible property is initialized like this:
public override void Initialize(IComponent component)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(component.GetType());
PropertyDescriptor descriptor = properties["Visible"];
if (((descriptor == null) || (descriptor.PropertyType != typeof(bool))) || !descriptor.ShouldSerializeValue(component))
{
this.Visible = true;
}
else
{
this.Visible = (bool) descriptor.GetValue(component);
}
...
}
descriptor.ShouldSerializeValue(component) for Control.Visible is always false in case of newly created control.
Designer.Visible property:
private bool Visible
{
get
{
return (bool) base.ShadowProperties["Visible"];
}
set
{
base.ShadowProperties["Visible"] = value;
}
}
In the Designer.PreFilterProperties() actual Visible property of the Control is shadowed by Visible property of the designer.
Now, when the designer is initialized(in my code that's happening when I'm creating component designerHost.CreateComponent) newCmbx.Visible is always true.
Why it is so? Because Visible property of the Control is used in painting of the control(on the designer surface as well). If I set newCmbx.Visible = false it just disappears from the design surface (but still serializes from the Visible property of the designer) - that's bad, so by design of the Control class, when Control is instantiated, it is always Visible so that it could be visible on the design surface. Any subsequent changes in Visible property influence Visible property of the designer, not Control itself (in the context of working in Designer mode).
So, what I need in order to solve that problem is Visible property of the designer.
Correct code looks like this:
foreach (OldCombo oldCmbx in OldCmbxs())
{
bool _visible = GetVisiblePropThroughReflection(designerHost.GetDesigner(oldCmbx));
...
NewCombo newCmbx = designerHost.CreateComponent(NewComboType, oldcmbx.Name) as NewCmbx;
...
SetVisiblePropThroughReflection(designerHost.GetDesigner(newCmbx), _visible);
...
designerHost.DestroyComponent(oldCmbx);
}
From within the code-behind of an ASP .NET web user-control (ascx) I need to get access (at runtime) to its parent, a div element. The aim is simple as to modify the visibility of the mentioned parent div.
I can not touch so much of the web-page code so I'd need a solution requiring only modifications in the user-control's code behind.
So in the HTML "part" of the code of the web page I have this:
<div id="parentDIV" runat="server">
<uc:MyUserControl ID="myUserControlInstance" runat="server" />
</div>
I'd like to do in the code behind of the user-control something like this:
this.Container.Visible = false;
Note that I'm not asking if it is a good practise or not to do this.
EDIT:
The user-control code behind does not "know" about the ID of the parent DIV.
I would hide it on the client. Decorate your user control container (div?) with a class like "awesomeUserControl". Then emit some javascript using the ScriptManager object to hide the parent like this:
ScriptManager.RegisterStartupScript(this, this.GetType(), "HideMyAwesomeUserControl", "$('.awesomeUserControl').parent().hide();", true);
The better way...
What you should do is to create a custom event in your user control, to which your container will subscribe - very much like subscribing to a button event, only this is your custom control. This event passes information to your container which can then discern from it what it needs, such as whether or not the div should/not be visible.
It might look something like:
protected void Page_Load(object sender, EventArgs e)
{
this.myuserControl.Update += new MyUserControlUpdateEventHandler(myuserControl_Update);
}
void myuserControl_Update(object sender, MyuserControlEventArgs e)
{
this.parentDiv.visible = !e.ShouldHideUI;
}
This method will decouple your parent with the user control, i.e. your user control doesn't have to have any knowledge at all of the parent's controls, nor should it.
If you are curious, here is a rough example of how your user control will define such an event:
public class MyuserControlEventArgs : EventArgs
{
public bool ShouldHideUI { get;set;}
public MyuserControlEventArgs (bool shouldHideUI)
{
this.ShouldHideUI = shouldHideUI;
}
}
public delegate void MyUserControlUpdateEventHandler(object sender, MyuserControlEventArgs e);
public event MyUserControlUpdateEventHandler Update;
protected void OnUpdate(MyuserControlEventArgs e)
{
if (Update!= null)
Update(this, e);
}
Your user control will simply need to call OnUpdate whenever it feels its subscribers need to know about it.
The Quick and Dirty way...
If you need quick and dirty, then try this (inside your user control):
TheParentControl parentControl = (TheParentControl)this.Parent;
parentControl.ParentDiv.Visible = true;
The key is to cast to the appropriate type (apparently your user control would know what type of parent it has), then set the parent's property. You might expose your div as a property in the parent control. Note, that parent could be ANY control (page, FooControl, BarControl, whatever) whose control collection your user control resides. Once you get a handle to the parent, you can even FindControl() to find a control by name.
You're almost there....
this.Parent.Visible = false;
When all controls get rendered, the HTML Parent child controls can be determined like below.
I am using while loop, so in case you add some other intermediate control, it may not give crash or unexpected results.
public Control ParentControl
{
get
{
Control ctl = this.Parent;
while (true)
{
if (ctl == null) break;
if (ctl.ID.Equals("parentDIV"))
{
break;
}
ctl = ctl.Parent;
}
return ctl;
}
}
if(ParentControl != null)
ParentControl.Visible = true|false;
Am I missing something, it sounds like you have a usercontrol and an aspx page (both have code behind's).
The user control appears to have been added to the aspx page, wrapped in a div. YOu've made the div control runat server (though you can still do this via htmlcontrol).
All you ned to do to manage the div is:
parentDIV.visible = false;
or whatever you need to do with the div.
Why does the UC code behind need to know about the APSX pages DIV, it doesn't.
I have an application which uses a FlowLayoutPanel with a lot of Custom UserControls in it. The Custom UserControls contains a Label.
The problem:
When the Label is updated the FlowLayoutPanel automatically scrolls it into view (Similar to the FlowLayoutPanel.ScrollControlIntoView() function).
This is the code snippet that makes the FlowLayoutPanel Scroll:
private void DownloadChanged(Object sender, DownloadProgressChangedEventArgs e)
{
progressDownload.Value = e.ProgressPercentage;
lblDownloaded.Text = e.BytesReceived.ToString() + " / " + e.TotalBytesToReceive.ToString();
}
I have been trying to find an event in the FlowLayoutPanel which I can intercept and stop it from scrolling when a child updates but I have not had any luck so far.
Is it possible to do this? If yes, how would I go about it? Thanks!
If having scrolling issues when clicking on a control in a FlowlayoutPanel,
use an inherited control:
public class MyFlowLayoutPanel : FlowLayoutPanel
{
protected override System.Drawing.Point ScrollToControl(Control activeControl)
{
//return base.ScrollToControl(activeControl);
return this.AutoScrollPosition;
}
}
https://social.msdn.microsoft.com/Forums/windows/en-US/cb8ac2d4-5940-4ed2-9f09-22cd4b76032b/suppressing-automatic-scrolling-within-flowlayoutpanel-with-autoscroll?forum=winforms
Setting the the Label's AutoSize Property to False seems to do the trick.
Read more here: Similar Issue