I'm trying to create a custom server control that is just a textbox with an AJAX asp.net MASKEDEDITEXTENDER to valid the control when it loses focus to ensure that a proper date has been entered.
This is all I have so far and I'm able to build the control but no validation is taking place what am I doing wrong here.
namespace One_Eva_Control_Library
{
[ToolboxData("<{0}:Valid_Date_Textbox runat=server></{0}:Valid_Date_Textbox>")]
public class Valid_Date_Textbox : System.Web.UI.WebControls.TextBox
{
#region Methods
/// <summary>
/// Creates Validator
/// </summary>
/// <param name="e">Init eventArg</param>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
MaskedEditExtender meDateValidator = new MaskedEditExtender();
meDateValidator.ID = "dateExtender";
meDateValidator.Mask = "99/99/9999";
meDateValidator.MessageValidatorTip = true;
meDateValidator.MaskType = MaskedEditType.Date;
meDateValidator.UserDateFormat = MaskedEditUserDateFormat.DayMonthYear;
meDateValidator.CultureName = "en-GB";
MaskedEditValidator meEditValidtor = new MaskedEditValidator();
meEditValidtor.ControlExtender = meDateValidator.ID;
meEditValidtor.ControlToValidate = base.ID;
meEditValidtor.InvalidValueMessage = "Invalid Date";
meEditValidtor.Display = ValidatorDisplay.Dynamic;
meEditValidtor.TooltipMessage = "Input date in 99/99/9999 format";
meEditValidtor.InvalidValueMessage = "*";
meEditValidtor.ValidationGroup = "MKE";
}
#endregion
}
You need to add them to the controls collection. I don't know that inheriting from TextBox will get you what you want; I think you may need to inherit from CompositeControl, and override CreateChildControls and create the textbox, and the extender/validator. Just make sure to add all of them to the controls collection...
Related
Recently I was put on new a team at work and the lead told me to write unit tests for the code they had written. I'm really not sure where to start. The application is a WPF written in C#. I'm a newbie to both WPF and C#. They mentioned using Xunit.
Here is first two functions of the class. There is mix of protected and public functions i have to unit test,
The class type is public class DataTableModel<T> : ViewModelBase
public DataTableModel()
{
//Setup Drag and Drop Commands:
RecordReceivedCommand = new DataTableReceivedCommand<T>(this);
RecordRemovedCommand = new DataTableRemovedCommand<T>(this);
RecordInsertedCommand = new DataTableInsertedCommand<T>(this);
View = CollectionViewSource.GetDefaultView(Records);
}
/// <summary>
/// This method sets up the properties for the table. By default, the first DisplayOption is selected, no search criteria is applies, and only 10 records should be returned.
/// </summary>
/// <param name="displayOption">The selected display option</param>
protected void InstantiateTable(int displayOption = 0)
{
_displayOption = displayOption;
_searchCriteria = "";
_displayAmount = "10";
_currentPage = 1;
_userMessage = "Retrieving data...";
TriggerUpdate();
}
These functions are called from above so I thought I'd include them.
/// <summary>
/// This method is responsible for handling the updates to the recordset that the DataGrid will display.
/// Upon changes to the search criteria, display amount, display option and the current page, this method will be triggered
/// </summary>
/// <param name="resetPage">Inidicates whether the grid should return to page 1.</param>
protected void TriggerUpdate(bool resetPage = false)
{
_currentPage = resetPage ? 1 : _currentPage; //only reset to the first page if indicated
UserMessage = "Retrieving data...";
//Retrieve the records if the delegate has been set
GetRecords?.Invoke();
UserMessage = Records.Count == 0 ? "No data found" : "";
Message_ZIndex = !String.IsNullOrWhiteSpace(UserMessage) ? 1 : -1;
//update the page navigations button's settings when the pages are reset
UpdatePagination();
}
/// <summary>
/// Update the ability to navigate through the datatable's pages.
/// Upon changes the the search criteria, display amount, display option, the number of pages and the current page, this method will be
/// triggered
/// </summary>
private void UpdatePagination()
{
if (Pages > 1)
{
if (_currentPage == 1)
{
GoToFirstPage = false;
GoToPrevPage = false;
GoToNextPage = true;
GoToLastPage = true;
}
else if (_currentPage == Pages)
{
GoToFirstPage = true;
GoToPrevPage = true;
GoToNextPage = false;
GoToLastPage = false;
}
else
{
GoToFirstPage = true;
GoToPrevPage = true;
GoToNextPage = true;
GoToLastPage = true;
}
}
else
{
GoToFirstPage = false;
GoToPrevPage = false;
GoToNextPage = false;
GoToLastPage = false;
}
}
/// <summary>
/// Get's the information for the datatable's columns
/// (NOTE: This method is currently only called via ".Invoke" within the DataTable control.)
/// </summary>
/// <returns>A List of the DataTableDisplay attributes for the columns in the table</returns>
public List<DataTableDisplay> GetTableColumnInformation()
{
List<DataTableDisplay> attributes = new List<DataTableDisplay>();
PropertyInfo[] properties = typeof(T).GetProperties();
foreach(PropertyInfo property in properties)
{
DataTableDisplay attr = property.GetCustomAttribute<DataTableDisplay>(false);
if (attr != null && !String.IsNullOrWhiteSpace(attr.ColumnTitle))
{
attributes.Add(attr);
}
}
return attributes;
}
At first I wanted to test the constructor, but then I didn't know how to check for the command vars so i moved on to the InstantiateTable function. This is what i got. Still having to create object so using the Constructor but when i tried calling x.InstantiateTable() I noticed it was protected so I cant do that.
Test case for creating an DataTableModel Object. It had dynamic type so i just made it int.
[Fact]
public void DataTableModel_Created()
{
DataTableModel<int> x = new DataTableModel<int>();
Assert.Equal(0, x.DisplayOption);
Assert.Equal("", x.SearchCriteria);
Assert.Equal("10", x.DisplayAmount);
Assert.Equal(1, x.CurrentPage);
Assert.Equal("Retrieving data...", x.UserMessage);
}
Another protected function i have to unit test.
protected List<T> UpdateTable(List<T> data)
{
_totalCount = data.Count;
int recordLimit = String.IsNullOrEmpty(DisplayAmount) ? 0 : Convert.ToInt32(DisplayAmount);
int startingRecord = recordLimit == 0 ? 0 : (_currentPage == 1 ? 1 : 1 + (recordLimit * (_currentPage - 1)));
int recordsToSkip = (CurrentPage - 1) * recordLimit;
int endingRecord = recordLimit == 0 ? 0 : recordLimit > _totalCount ? _totalCount : startingRecord + recordLimit - 1;
Pages = recordLimit == 0 ? 0 : _totalCount <= recordLimit ? 1 : _totalCount % recordLimit > 0 ? (_totalCount / recordLimit) + 1 : _totalCount / recordLimit;
List<T> displayRecords = data.Skip(recordsToSkip).Take(recordLimit).ToList();
DisplayMessage = endingRecord <= _totalCount ? $"Showing {(displayRecords.Count == 0 ? 0 : startingRecord)} to {endingRecord} of {_totalCount} entries" : $"Showing {startingRecord} to {_totalCount} of {_totalCount} entries";
return displayRecords;
}
And a delegate function? I'm supposed to test
public delegate List<T> Filter(List<T> data);
I am not sure how to approach. The few unit tests i did in university were basic objects and didn't call other objects and what not. I have read about mocking and stubbing objects, I think it may be good to mock database to populate the tables.
Do not unit-test functions. Unit-test view-models.
A view-model exposes properties and commands which are bound by XAML to GUI controls so that the user can interact with them.
All these properties and commands are already public, otherwise they would not be visible from XAML, so your tests can access them too.
Most C# programmers will not think twice before converting private and protected to public, or converting to internal and then using InternalsVisibleTo, but in my opinion that's all misguided. We must be testing against the interface, not against the implementation; therefore, we must be engaging in black-box testing, not white-box testing.
When it comes to testing view-models in WPF, this means you should only test things that are exposed to XAML.
So, your tests should set values to view-model properties as if these values were set by GUI controls, invoke view-model commands as if these commands were triggered by GUI buttons.
Then, your tests should examine nothing but how the values of view-model properties change as a result. That's what the user would see on the screen.
I have written this code in visual studio 2013 utilizing .net v4.5. The problem I am having is that I am now having to drop down to .net v3.5 and the dynamic keyword is throwing an error as missing an assembly reference. Is there an equivalent type to 'dynamic' in .net v3.5 or a way for me to achieve the same results as below?
I thought I may have found my answer here, but var is throwing errors when I add the .Attributes or .Text property modifications.
private void CreateControl<T>(string objText,
Panel pnl,
string HTMLTag = "<td>",
string applicantID = "",
EventHandler hndl = null)
{
pnl.Controls.Add(new LiteralControl(HTMLTag));
dynamic obj = Activator.CreateInstance(typeof(T));
obj.Text = objText;
if (applicantID != string.Empty)
{
obj.Attributes.Add("ApplicantID", applicantID);
}
if (hndl != null)
{
obj.Click += new EventHandler(hndl);
}
pnl.Controls.Add(obj);
pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
}
Instead of trying to hack this together in some bound to fail way and since there isn't a 'dynamic' control in .net v3.5, I have instead decided to just completely forgo this method and wrote some overloads instead. This way seems safer at this point; works the same, just a bit more code...
#region CreateControl() Overloads
/// <summary>
/// Creates a LinkButton control.
/// </summary>
/// <param name="objText">.Text property of this LinkButton control.</param>
/// <param name="pnl">Panel this control will be attached to.</param>
/// <param name="hndl">Event handler attached to this LinkButton control.</param>
/// <param name="HTMLTag">Opening tag used to contain this control.</param>
private void CreateControl(string objText,
Panel pnl,
EventHandler hndl,
string HTMLTag)
{
pnl.Controls.Add(new LiteralControl(HTMLTag));
LinkButton obj = new LinkButton();
obj.Text = objText;
obj.Click += new EventHandler(hndl);
pnl.Controls.Add(obj);
pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
}
/// <summary>
/// Creates a Label control.
/// </summary>
/// <param name="objText">.Text property of this Label control.</param>
/// <param name="pnl">Panel this control will be attached to.</param>
/// <param name="HTMLTag">Opening tag used to contain this control.</param>
private void CreateControl(string objText,
Panel pnl,
string HTMLTag)
{
pnl.Controls.Add(new LiteralControl(HTMLTag));
Label obj = new Label();
obj.Text = objText;
pnl.Controls.Add(obj);
pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
}
/// <summary>
/// Creates the specified literal control.
/// </summary>
/// <param name="ControlText">HTML text containing instructions for creating the desired literal control.</param>
/// <param name="pnl">Panel this literal control will be attached to.</param>
private void CreateControl(string ControlText,
Panel pnl)
{
pnl.Controls.Add(new LiteralControl(ControlText));
}
#endregion
Is there an equivalent type to 'dynamic' in .net v3.5
No. dynamic requires .NET 4.0.
or a way for me to achieve the same results as below?
You could use reflection instead of dynamic to create the control and add your event handlers.
However, since this appears to be one of a few custom controls you're creating (given the attributes, etc), you may be able to constrain to an interface or base class, which would allow you to create the items and use those shared properties directly.
Based on your code, it looks like you're writing a generic method to pass in some unknown controls and attach them to a panel.
It also looks like you're dealing with different types of controls; i.e., not all WebControls have Text, and Attributes, AND Click properties;
This is a bit hacky but works in 3.5 - you can just use casting of the various underlying types or interfaces to access the needed properties, something like this:
private void CreateControl<T>(string objText, Panel pnl, string HTMLTag,
string applicantID, EventHandler hndl)
where T : Control, new()
{
pnl.Controls.Add(new LiteralControl(HTMLTag));
T obj = new T();
if (obj is ITextControl) (obj as ITextControl).Text = objText;
if (applicantID != string.Empty && obj is WebControl)
(obj as WebControl).Attributes.Add("ApplicantID", applicantID);
if (obj is IButtonControl)
{
(obj as IButtonControl).Text = objText;
if (hndl != null)
{
(obj as IButtonControl).Click += new EventHandler(hndl);
}
}
pnl.Controls.Add(obj as Control);
pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
}
Test code:
protected void Page_Load(object sender, EventArgs e)
{
var panel = new Panel();
CreateControl<Button>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
CreateControl<Label>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
CreateControl<Panel>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
CreateControl<Literal>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
//This won't compile because object doesn't fit <control> constraint
//CreateControl<object>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
}
To be honest I'm not 100% sure I like this approach. I might use some more specific methods and possibly method overloading to get more specific with different types of control creation, but this may help point you in the right direction.
Note that optional parameters are also not yet "invented" in C# 3.0 which shipped with .net 3.5, so you have to actually pass in all of the values.
dynamic keyword is available on .net 4.x and is a simple way to store any kind of value, it just resolve his type in runtime. It has been useful to me working with JSON strings.
string jsonValue = "{name:'Pedro',lastName:'Mora'}";
dynamic Variable = new JavascriptSerializer().Deserialize<dynamic>(jsonValue);
return Variable.name;
//It will return "Pedro"
Thing is that you have to be sure that the value won't be null and the properties or attributes or methods or something refered to the object exists and it takes it's values on runtime.
I've created a ListView in a new WPF window and also a function that populates the ListView when it is called. This function just takes the URL of my web server where I've stored the data, increments the "id" and gets the data and stores it in the ListView. Therefore it populates the ListView with a certain number of items.
The problem I'm facing is that I want to add two buttons, ON & OFF, to each ListView item as it gets populated programmatically. i.e, if 16 items are added, I want 2 buttons for each item, and if it's 12 items, the similar procedure. Here's my code:
namespace user_login
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Window1 W = new Window1();
public MainWindow()
{
InitializeComponent();
}
public void populate()
{
int i;
int num = 16;
for (i = 1; i <= num; i++)
{
string val = Convert.ToString(i);
string currentUrl = "http://xpleria.com/devices.php?query=dev&id=";
string newUrlWithChangedSort = ReplaceQueryStringParam(currentUrl, "id", val);
string result = getcontent(newUrlWithChangedSort);
W.list1.Items.Add(result);
}
}
public string getcontent(string URL)
{
string content = "";
// Get HTML data
WebClient client = new WebClient();
try
{
content = client.DownloadString(URL);
}
catch (Exception)
{
System.Windows.Forms.MessageBox.Show("No Connection detected!!!");
}
return content;
}
public static string ReplaceQueryStringParam(string currentPageUrl, string paramToReplace, string newValue)
{
string urlWithoutQuery = currentPageUrl.IndexOf('?') >= 0
? currentPageUrl.Substring(0, currentPageUrl.IndexOf('?'))
: currentPageUrl;
string queryString = currentPageUrl.IndexOf('?') >= 0
? currentPageUrl.Substring(currentPageUrl.IndexOf('?'))
: null;
var queryParamList = queryString != null
? HttpUtility.ParseQueryString(queryString)
: HttpUtility.ParseQueryString(string.Empty);
if (queryParamList[paramToReplace] != null)
{
queryParamList[paramToReplace] = newValue;
}
else
{
queryParamList.Add(paramToReplace, newValue);
}
return String.Format("{0}?{1}", urlWithoutQuery, queryParamList);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
string user = textbox1.Text;
string password = textbox2.Password;
string currentUrl = "http://xpleria.com/login.php?query=login&user=wcam&pass=wireless";
string newUrlWithChangedSort = ReplaceQueryStringParam(currentUrl, "user", user);
string newUrl = newUrlWithChangedSort;
string FinalUrl = ReplaceQueryStringParam(newUrl, "pass", password);
string result= getcontent(FinalUrl);
string value = result.Substring(0, 8);
string invalid = "xpleria0";
string valid = "xpleria1";
if (value.Equals(invalid))
{
System.Windows.MessageBox.Show("The Username and/or Password you have entered is invalid, please try again");
}
else if (value.Equals(valid))
{
string sessionID = result.Substring(8, 32);
System.Windows.MessageBox.Show("HI, WELCOME CLETA");
this.Close();
using (new user_login.loading.PleaseWait(this.Location))
{
W.Show();
populate();
}
}
}
public System.Drawing.Point Location { get; set; }
}
}
I'm going to recommend you take a step back and start giving some serious consideration to organizing your code. I realize this isn't an answer to the question you asked but it is the answer to the question you should be asking.
First of all, all code relating to the retrieval of these items from the URL should be moved into a class of some kind. This class should accept the URL string as a constructor parameter and gather all the appropriate data. You should then create another class which you will use to populate with the data for each individual item and then expose this list. By the time you're done the code in your window should little more complex than:
var ItemsGetter = new ItemsGetter(URL);
foreach(var Item in ItemsGetter.Items)
{
// Populate the ListView
}
Once you're done with that I recommend you create a UserControl. User controls are extremely useful in situations where you need to represent a dynamic number of data entities each with their own set of controls which allow operations to be performed on each one. You should create a UserControl with a label and the two buttons you need. The UserControl's constructor should expect a parameter of the data type you created to represent each one of your classes. From there you can have the buttons operate on the data type as necessary.
Finally, you'll probably need a way to have the UserControl interact with the Window. Say for example one of your buttons is "Delete". You'd probably want the item to disappear from the list once the operation is complete. Don't be tempted to tie in your control with the Window by passing it as a parameter or something. Instead, read up on Action events and learn how you can create an event on the user control which you bind in the foreach loop of the Window when you're populating the list view. When the UserControl has completed the delete operation triggered by the button you can raise the UserControl's event which will prompt the Window to remove the control from the List View.
Last but not least, NAME YOUR CONTROLS.
Hopefully this helps.
I am trying to do the following to hide the title field from the new and edit form but its still visible.
pls help
/// <summary>
/// Adds source list and content type.
/// </summary>
/// <param name="currentWeb"></param>
private void AddSourcesList(SPWeb currentWeb)
{
currentWeb.AllowUnsafeUpdates = true;
#region Add Source content type.
if(currentWeb.ContentTypes[SponsoringCommon.Constants.CONTENTTYPES_SOURCES_NAME] == null)
{
#region Hides title column
currentWeb.Lists.Add(SponsoringCommon.Constants.LISTNAMES_SOURCES_NAME, string.Empty, SPListTemplateType.GenericList);
SPList sourceList = currentWeb.Lists.TryGetList(SponsoringCommon.Constants.LISTNAMES_SOURCES_NAME);
SPField titleField = sourceList.Fields.GetField("Title");
titleField.Required = false;
titleField.ShowInEditForm = false;
titleField.ShowInDisplayForm = false;
titleField.ShowInNewForm = false;
titleField.Hidden = true;
titleField.Update();
#endregion
I cannot see the rest of the code, but I had similar problem, and the thing I was missing is to .Update() the List and the Web. So in your case try to update sourceList and at the end currentWeb.
Hopefully, it will help solve your problem.
I have a custom server control which wraps a RadEditor (basically a textarea). I am trying to add a CustomValidator to it dynamically, but I keep getting this error on initial pageload
Unable to find control id 'RadEditor1' referenced by the
'ControlToValidate' property of ''.
This is the code I'm using inside my server control to create the CustomValidator:
protected override void OnInit(EventArgs e)
{
var validator = new CustomValidator();
validator.CssClass = "validator-error";
validator.Display = ValidatorDisplay.Dynamic;
validator.ControlToValidate = this.ID;
validator.Text = "You've exceeded the maximum allowed length for this field";
validator.ClientValidationFunction = "checkLength";
this.Controls.Add(validator);
base.OnInit(e);
}
The problem is that RadEditor implements INamingContainer, so ASP.NET winds up searching among your server control's children for a control named RadEditor1. Of course, it's unsuccessful because RadEditor1 doesn't have a child control named RadEditor1.
The trick I use is to choose a special ID like "." to mean the parent control itself:
protected override Control FindControl(string id, int pathOffset)
{
return (id == ".") ? this : base.FindControl(id, pathOffset);
}
Then use "." as the ControlToValidate:
validator.ControlToValidate = ".";