I have the need for a dropdownlist with the U.S. states in it. I could need this dropdownlist on various pages. Instead of always having to create a listitem for each state, I want a simple control. I don't want a UserControl - I want to extend the existing dropdownlist control. I know I have done this before at a previous employer, but for the life of me I can't remember how to do it!
Can't I just do something like this for each state? If so, where?
MyBase.Items.Add(New ListItem("Illinois","IL"))
Any ideas out there?
Thanks
All you have to do is create a new class and inherit from the appropriate control:
/// <summary>
/// </summary>
[DefaultProperty("DataTable"),
ToolboxData("<{0}:ExtendedDropDownlist runat=server></{0}:ExtendedDropDownlist>")]
public class ExtendedDropDownList : DropDownList
/// <summary>
/// Render this control to the output
/// parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to
/// write out to </param>
protected override void Render(HtmlTextWriter output)
{
//output.Write(Text);
base.Render(output);
}
In the constructor just add the appropriate listbox items like you have.
You may need to put it in a different project and reference the dll. I think I remember something about that, but it's been a while since I have had to do it.
Extend DropDownList control and override OnLoad event and add your items like that :
protected override void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.Items.Add(new ListItem("Illinois","IL"));
}
}
<ToolboxData("<{0}:StateDropDownList runat=server></{0}:StateDropDownList>")> _
Public Class StateDropDownList
Inherits DropDownList
Protected Overrides Sub RenderContents(ByVal output As HtmlTextWriter)
output.Write(Text)
End Sub
Protected Overrides Sub RenderChildren(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.RenderChildren(writer)
End Sub
Private Sub LoadStates()
MyBase.Items.Add(New ListItem("Alabama", "AL"))
'Additional states removed for size
MyBase.Items.Add(New ListItem("Wyoming", "WY"))
End Sub
Public Sub New()
'tried does not work
' LoadStates()
End Sub
Private Sub StateDropDownList_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
'tried does not work
' LoadStates()
End Sub
Private Sub StateDropDownList_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'tried does not work
'If Not Page.IsPostBack Then
' LoadStates()
'End If
End Sub
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.Render(writer)
End Sub
End Class
public class DropDownListStates : System.Web.UI.WebControls.DropDownList
{
protected override void CreateChildControls()
{
if (Items.Count > 0) return;
Items.Add(new System.Web.UI.WebControls.ListItem("AL"));
// other states here...
Items.Add(new System.Web.UI.WebControls.ListItem("WY"));
}
}
Related
I have the below custom module in an asp.net web application. The module works from chrome on my PC but when I try to access a video from Android I get an error because the userid (_context.User) is not set. This all occurs after I have logged into the application. Therefore _context.User should be set.
I would have thought because at this level you are dealing with HTTP Requests and Responses that the module would work for any device.
I have two questions.
Is there a way to make this work?
What is the difference between the requests sent by the Android tablet and PC to cause this issue?
Public Class VideoSecurityModule
Implements IHttpModule
Implements IRequiresSessionState
Private WithEvents _context As HttpApplication
Public Sub Dispose() Implements IHttpModule.Dispose
End Sub
Dim myUserManager As UserManager
Public Sub Init(ByVal context As HttpApplication) Implements IHttpModule.Init
_context = context
myUserManager = New UserManager
End Sub
Public Sub Log(value As String, ParamArray args As Object())
Dim message As String = String.Format(value, args)
Dim messagePrefix As String = String.Format("{0},{1},{2},{3}", UserAgent, Url, SessionId, message)
LogManager.WriteMessage(messagePrefix, "")
End Sub
Private ReadOnly Property UserAgent() As String
Get
Try
Return _context.Request.UserAgent
Catch ex As Exception
Return "No User Agent"
End Try
End Get
End Property
Private ReadOnly Property Url() As String
Get
Try
Return _context.Request.Url.PathAndQuery
Catch ex As Exception
Return "No URL"
End Try
End Get
End Property
Private ReadOnly Property SessionId() As String
Get
Try
Return __context.Session.SessionID
Catch ex As Exception
Return "No URL"
End Try
End Get
End Property
Public ReadOnly Property IsReusable() As Boolean
' IsReusable must be set to false since class has a member!
Get
Return True
End Get
End Property
Public Sub OnAuthorizeRequest(ByVal source As Object, ByVal e As EventArgs) Handles _context.AuthorizeRequest
If IsVideoUrl() Then
Dim userId As Integer = GetLoggedInUsersId()
Log("UserRequiresAuthorization({0}): {1}", userId, UserRequiresAuthorization(userId))
Log("UserIsAssignedToCourseContainingVideo({0}): {1}", userId, UserIsAssignedToCourseContainingVideo(userId))
' if user is not assigned to a course that utilizes the video or the user is not in role super user or system admin
If (UserRequiresAuthorization(userId) AndAlso Not UserIsAssignedToCourseContainingVideo(userId)) Then
SendAuthenticationRequiredResponse()
End If
End If
End Sub
Private Function GetLoggedInUsersId() As Integer
Dim userId As Integer = 0
If (Not _context.User Is Nothing) Then
userId = myUserManager.GetUserIdByUserName(_context.User.Identity.Name)
End If
Log("userId:{0}", userId)
Return userId
End Function
Private Sub SendAuthenticationRequiredResponse()
Const networkAuthenticationRequiredStatusCode As Integer = 511
_context.Response.StatusCode = networkAuthenticationRequiredStatusCode
_context.Response.ClearContent()
_context.Response.Write("UnAuthorized User")
Log("UnAuthorized User: {0}", "")
_context.Response.End()
End Sub
Private Function IsVideoUrl() As Boolean
Dim fileLocation As String = System.Configuration.ConfigurationManager.AppSettings("VideoLocation")
Log("url:{0}", _context.Request.Url)
Log("IsVideoUrl:{0}", _context.Request.FilePath.ToLower().Contains(fileLocation.ToLower()))
Return _context.Request.FilePath.ToLower().Contains(fileLocation.ToLower())
End Function
Private Function UserDoesNotRequireAuthorization(userId As Integer) As Boolean
Return myUserManager.IsSysAdmin(userId) OrElse myUserManager.IsSuperUser(userId)
End Function
Private Function UserRequiresAuthorization(userId As Integer) As Boolean
Dim result As Boolean = Not UserDoesNotRequireAuthorization(userId)
Return result
End Function
''' <summary>
''' Returns true if the in-putted user (logged in user) has been allocated to a course that utilize video specified in this request
''' </summary>
Private Function UserIsAssignedToCourseContainingVideo(userId As Integer) As Boolean
' ... code removed for clarity
End Function
End Class
This is a known issue with a number versions of android. My limited research suggests that video requests are passed to a separate component in android called stagefright. Stagefright can not handle cookies and therefore no authentication cookie is passed to the web application resulting in the _context.User property not being set.
The following links provide more in depth details.
Do Mobile Browsers send httpOnly cookies via the HTML5 Audio-Tag?
https://code.google.com/p/android/issues/detail?id=17553
I have a property in my View Model
public const string WelcomeTitlePropertyName = "WelcomeTitle";
private string _welcomeTitle = string.Empty;
/// <summary>
/// Gets the WelcomeTitle property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public string WelcomeTitle
{
get
{
return _welcomeTitle;
}
set
{
RaisePropertyChanging(WelcomeTitlePropertyName);
_welcomeTitle = value;
RaisePropertyChanged(WelcomeTitlePropertyName);
}
}
This is hooked up to a textbox and has 2 way binding.
Now I have a KeyDown event that I need to get the current length of the "WelcomeTitle" property
public ICommand AutoComplete
{
get
{
return new RelayCommand<KeyEventArgs>(e =>
{
var length = WelcomeTitle.Length;
});
}
}
Yep what I am finding is that WelcomeTitle property does not get updated till the user leaves the textbox. This does not work for me as I need to know the length(and later the current value in WelcomeTitle) and keydown.
How can I get around this? In codebehind this is no problem.
In WPF it would be easily achieved by setting UpdateSourceTrigger="PropertyChanged" in the binding; unfortunately, this is not possible with Windows Phone, so you need a workaround. A few options are described in this question.
I have a Windows Forms with a few TextBoxes and a button. The button has a mnemonic key to get fired (example &OK). I'm subscribed to the Leave event of the TextBox in order to make a validation and update the related controls based on the user input (for example, if I change the cost of a product, the rentability proportion is going to be updated). If I click the OK button, everything works OK but if I use the mnemonic key (Alt+O), the Leave event of the TextBox is fired after the Click event of the button. Because of this, my TextBoxes are not updated before the Click event of the button. Any ideas?
Summary of normal behavior:
- Update TextBox value and click on OK button --> TextBox fires Leave Event and values are updated. Then, The Click event of the is handled.
Summary of strange behavior:
- Update TextBox value and press the shotcut key (Alt+O) for the OK button --> Click Event of the button is fired and then the Leave event of the TextBox is fired.
Thanks in advanced.
Try with some trick ..
Dim sButtonBy as String
Private Sub TextBox1_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.GotFocus
sButtonBy = ""
End Sub
Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
If e.Alt Then sButtonBy = "KB"
End Sub
Private Sub TextBox1_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Leave
UpdateIt()
End Sub
Sub UpdateIt()
'codes here
End Sub
EDITED :
Use this sub to handle every button that added dynamically
AddHandler Button1.Click, AddressOf Me.Buttons_Click
Private Sub Buttons_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
If sButtonBy = "KB" Then updateit()
'codes here
End Sub
You may use "LostFocus" Event Instead of using "Leave"...
I finally found a solution using pieces of code from different places. I think that it's important to write it down here because I haven't found the complete answer anywhere. Even a question related to this issue is difficult to find. Let me explain what I did:
1) Override the method ProcessMnemonic in the Form.
protected override bool ProcessMnemonic(char charCode)
{
// get the mnemonic key of the button that submits the form (accepts the form or performs some action)
char mnemonicChar = DesignerHelper.GetMnemonicChar(btnCreate);
// check if the button has a mnemonic key and if the mnemonic key pressed corresponds to it
if (mnemonicChar != ' ' && charCode == mnemonicChar)
{
// get the control that is focused. this could be the textbox where the mnemonic key was pressed
Control ctrl = DesignerHelper.FindFocusedControl(this);
if (ctrl != null)
{
// fire the necessary event to update the state of the controls. in my case it's leave event.
DesignerHelper.FireEvent(ctrl, "Leave", new EventArgs());
}
}
return base.ProcessMnemonic(charCode);
}
2) Methods available in my own DesignerHelper class:
public static Control FindFocusedControl(Control control)
{
var container = control as ContainerControl;
while (container != null)
{
control = container.ActiveControl;
container = control as ContainerControl;
}
return control;
}
/// <summary>
/// Programatically fire an event handler of an object
/// </summary>
/// <param name="targetObject"></param>
/// <param name="eventName"></param>
/// <param name="e"></param>
public static void FireEvent(Object targetObject, string eventName, EventArgs e)
{
/*
* By convention event handlers are internally called by a protected
* method called OnEventName
* e.g.
* public event TextChanged
* is triggered by
* protected void OnTextChanged
*
* If the object didn't create an OnXxxx protected method,
* then you're screwed. But your alternative was over override
* the method and call it - so you'd be screwed the other way too.
*/
//Event thrower method name //e.g. OnTextChanged
String methodName = "On" + eventName;
MethodInfo mi = targetObject.GetType().GetMethod(
methodName,
BindingFlags.Instance | BindingFlags.NonPublic);
if (mi == null)
throw new ArgumentException("Cannot find event thrower named " + methodName);
mi.Invoke(targetObject, new object[] { e });
}
internal static char GetMnemonicChar(Button btn)
{
if (btn.UseMnemonic && btn.Text.Contains("&"))
{
return btn.Text.Substring(btn.Text.IndexOf("&") + 1, 1)[0];
}
return ' ';
}
I am working on a Windows Application form and I have a multi-line textbox that I would like to write output from another object. I saw there was a similar posting about getting text from one textbox to another form's textbox. However, I am working with the mainform and can't new up another one.
So how can I assign values to the mainform's .Text from another class?
You can create public properties on the form that get or set control properties e.g.
public partial class Form1 : Form
{
...
public string OperatorId
{
get { return OperatorIdField.Text.Trim().ToLower(); }
}
public string Password
{
get { return PasswordField.Text.Trim().ToLower(); }
}
...
}
(OperatorIdField and PasswordField are textboxes. In my example, the properties are read only i.e. they only have "get" methods. In your case you'd have to add "set" methods as well).
To expose the main form to other objects, you can create a static member that exposes the main form e.g.
static class Program
{
public static Form MainForm;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainForm = new Form1();
Application.Run(MainForm);
}
}
When another object needs to get the password, the code would be something like:
string password = Program.MainForm.Password;
Second form should have some event, that you call once you need change text box value in main form. And main form should be subscribed to this event and change text in at some eventHandler.
I have a control that is created like so:
public partial class MYControl : MyControlBase
{
public string InnerText {
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
public MYControl()
{
InitializeComponent();
}
}
partial class MYControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.listBox1 = new System.Windows.Forms.ListBox();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(28, 61);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 0;
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(7, 106);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(120, 95);
this.listBox1.TabIndex = 1;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(91, 42);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(35, 13);
this.label1.TabIndex = 2;
this.label1.Text = "label1";
//
// MYControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.label1);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.textBox1);
this.Name = "MYControl";
this.Size = new System.Drawing.Size(135, 214);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
}
MyControlBase contains the definition for the ListBox and TextBox. Now when I try to view this control in the Form Designer it gives me these errors:
The variable 'listBox1' is either
undeclared or was never assigned.
The variable 'textBox1' is either
undeclared or was never assigned.
This is obviously wrong as they are defined in MyControlBase with public access. Is there any way to massage Form Designer into allowing me to visually edit my control?
I think you'll have to use base.listBox1 and base.textBox1. They are defined in MyControlBase which is the base class, not the child class where you need to use the this keyword.
Dunno if this is your problem, but the designer has trouble when multiple types are defined in the same .cs file. If this is the case, try using a .cs file for each class.
Sometimes (always?) VS needs you to recompile your project before it can successfully display your usercontrol in the designer.
Also take into account that the VS designer actually loads up and instantiates your control to show it on the form. Your code is actually running in the background. However it will not have all the things it might expect to be there - like some global application variables or even other things on the same form. Your control has to be prepared for the "design mode". Otherwise if it generates an exception the designer will not show it. There was a property on every control (don't remember the name, but you should find it easily) that allowed you to determine if the control is in "design mode" or actually running.
The compiler is right (as it tends to be).
Neither textbox1 nor listbox1 are defined in the source code. They don't appear in either the derived class or the base class.
You should add the following to your base class:
protected System.Windows.Forms.TextBox textbox1;
protected System.Windows.Forms.ListBox listbox1;
You'll also need to do the changes outlined by Nazgulled if you decide to use private instead of protected for textbox1 and listbox1.