VS2008 Windows Form Designer does not like my control - visual-studio

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.

Related

Extending Umbraco ProfileModel with custom member model

I have the following code while updating the member account detail information:
/// <summary>
/// Verifies and edits the member fields.
/// </summary>
/// <param name="model"></param>
/// <returns>MemberDetailsFormViewModel containing all the editable information.</returns>
[Authorize]
public ActionResult HandleUpdateMemberDetails(MemberDetailsFormViewModel model)
{
if (ModelState.IsValid == false)
{
return CurrentUmbracoPage();
}
var memberService = Services.MemberService;
var member = memberService.GetById(Members.GetCurrentMemberId());
member.Properties[Constant.PropertyAlias.Authentication.FirstName].Value = model.FirstName;
member.Properties[Constant.PropertyAlias.Authentication.LastName].Value = model.LastName;
member.Properties[Constant.PropertyAlias.Authentication.AddressLine1].Value = model.AddressLine1;
member.Properties[Constant.PropertyAlias.Authentication.AddressLine2].Value = model.AddressLine2;
member.Properties[Constant.PropertyAlias.Authentication.TownCity].Value = model.TownCity;
member.Properties[Constant.PropertyAlias.Authentication.PostCode].Value = model.PostCode;
member.Properties[Constant.PropertyAlias.Authentication.County].Value = model.County;
member.Properties[Constant.PropertyAlias.Authentication.Country].Value = model.Country;
member.Properties[Constant.PropertyAlias.Authentication.PhoneNumber].Value = model.PhoneNumber;
memberService.Save(member);
if (Members.IsLoggedIn())
{
ViewBag.DetailSuccessfullyChanged = 1;
return CurrentUmbracoPage();
}
return View("/");
}
Although this solution works, I would like to do more elegant updating of the member.Properties["propertyName"].Value through extended ProfileModel with the following method of MembershipHelper: UpdateMemberProfile(ProfileModel model).
Useful links:
MembershipHelper documentation link.
Similar issue on OUR Umbraco
Has anyone managed to do something like this?
EDIT:
I see that Warren did something similiar on his GitHub.

Instantly Update Property in MVVM Light?

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.

ObjectStateEntry GetModifiedProperties() incorrectly detects change to byte[] property

Does Entity Framework incorrectly detect changes to images?
I have a "Person" entity class defined as follows;
public class Person
{
public int Id { get; set; }
public byte[] Photo { get; set; }
}
I have bound the Photo to a PictureBox control on my form using a datasource.
There form also uses a dynamically created bindingNavigator.
I also have written an audit log to populate captured changes
The procedure calls the ObjectContext DetectChanges() and then
var entries = ObjectContext.ObjectStateManager.GetObjectStateEntries()
Which contains an entry showing that the Photo has been modified.
entry.OriginalValues[name] matches entry.CurrentValues[name]
The Column is varbinary(MAX) in SQL Server and the size of the picture files I have loaded are under 1Mb
If I set all of the columns to null the error no longer occurs
The code I use to get the file is
private void LoadPhotoButton_Click(object sender, EventArgs e)
{
using (var dlg = new OpenFileDialog())
{
dlg.Filter = "JPEG files |*.jpg";
if (dlg.ShowDialog() == DialogResult.OK)
{
PhotoPictureBox.Image = Image.FromFile(dlg.FileName);
}
}
}
I note here that hex zero can be inserted as padding characters when these fields are involved in string conversion.... could the binding be doing that somehow?
If I delete the picturebox from the form, or even bind the control as a text box instead of a picturebox then the behaviour is correct ( not that a picture bound to a text box is any use )
I am able to work around the problem by not binding directly to the picture box.
Instead I just load it on the BindingSource_CurrentChanged event using
private void BindingSource_CurrentChanged(object sender, EventArgs e)
{
var obj = (Person) BindingSource.Current;
this.PictureBox.Image = byteArrayToImage( obj.Photo);
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
I am using my work around - documented at the end of the question as a make do answer.

How can i force the DbUpdateConcurrencyException to be raised even if i am passing the FormCollection to my Post action method instead of an object

i have the following action method inside my asp.net mvc web application , which will raise a DbUpdateConcurrencyException as intended to handle any concurrent conflicts that might happen:-
[HttpPost]
public ActionResult Edit(Assessment a)
{ try
{
if (ModelState.IsValid)
{
elearningrepository.UpdateAssessment(a);
elearningrepository.Save();
return RedirectToAction("Details", new { id = a.AssessmentID });
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var clientValues = (Assessment)entry.Entity;
ModelState.AddModelError(string.Empty, "The record you attempted to edit was"
+ "modified by another user after you got the original value.");
}
catch (DataException)
{
ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
}
return View(a);}
but to avoid any over binding attacks i have define a [Bind(Include = "Date, Title")] on the object class, but this raised a problem to me as the above action method will return an exception even if no concurrent conflict occur becuase the model binder will not be able to bind the object ID and other values ,, so i have changed my action method to the following:-
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
Assessment a = elearningrepository.GetAssessment(id);
try
{
if (TryUpdateModel(a))
{
elearningrepository.UpdateAssessment(a);
elearningrepository.Save();
return RedirectToAction("Details", new { id = a.AssessmentID });
}
}
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var clientValues = (Assessment)entry.Entity;
ModelState.AddModelError(string.Empty, "The record you attempted to edit was"
+ "modified by another user after you got the original value.");
}
catch (DataException)
{ ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
}return View(a);
but writting the action method as in the second approach will not raise the DbUpdateConcurrencyException under any situation (even if a concurrency conflict occurs!!!).
so me question is how i can make sure that the DbUpdateConcurrencyException will be raised if any conflict occur and at the same time to make sure that no over binding attack might occur by defining [Bind(Include = "Date, Title")]?
thanks in advance for any help and suggestions .
BR
Stop using forms collection and use a view model, thats a far better approach.
Also I have an action filter I wrote to handle the concurrency exceptions (MVC4 handles entity exceptions now finally has pat of validation just not the concurrency exceptions). Its a work in progress but should work ok as is, that much has been tested : )
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Data.Entity.Infrastructure;
using System.Reflection;
namespace Gecko.Framework.Mvc.ActionFilters
{
/// <summary>
/// Author: Adam Tuliper
/// adam.tuliper#gmail.com
/// completedevelopment.blogspot.com
/// www.secure-coding.com
/// Use freely, just please retain original credit.
///
/// This attribute attempts to intercept DbUpdateConcurrencyException to write out original/new values
/// to the screen for the user to review.
/// It assumes the following:
/// 1. There is a [Timestamp] attribute on an entity framework model property
/// 2. The only differences that we care about from the posted data to the record currently in the database are
/// only yhe model state field. We do not have access to a model at this point, as an exception was raised so there was no
/// return View(model) that we have a model to process from.
/// As such, we have to look at the fields in the modelstate and try to find matching fields on the entity and then display the differences.
/// This may not work in all cases.
/// This class will look at your model to get the property names. It will then check your
/// Entities current values vs. db values for these property names.
/// The behavior can be changed.
/// </summary>
public class HandleConcurrencyException : FilterAttribute, IExceptionFilter //ActionFilterAttribute
{
private PropertyMatchingMode _propertyMatchingMode;
/// <summary>
/// This defines when the concurrencyexception happens,
/// </summary>
public enum PropertyMatchingMode
{
/// <summary>
/// Uses only the field names in the model to check against the entity. This option is best when you are using
/// View Models with limited fields as opposed to an entity that has many fields. The ViewModel (or model) field names will
/// be used to check current posted values vs. db values on the entity itself.
/// </summary>
UseViewModelNamesToCheckEntity = 0,
/// <summary>
/// Use any non-matching value fields on the entity (except timestamp fields) to add errors to the ModelState.
/// </summary>
UseEntityFieldsOnly = 1,
/// <summary>
/// Tells the filter to not attempt to add field differences to the model state.
/// This means the end user will not see the specifics of which fields caused issues
/// </summary>
DontDisplayFieldClashes = 2
}
/// <summary>
/// The main method, called by the mvc runtime when an exception has occured.
/// This must be added as a global filter, or as an attribute on a class or action method.
/// </summary>
/// <param name="filterContext"></param>
public void OnException(ExceptionContext filterContext)
{
if (!filterContext.ExceptionHandled && filterContext.Exception is DbUpdateConcurrencyException)
{
//Get original and current entity values
DbUpdateConcurrencyException ex = (DbUpdateConcurrencyException)filterContext.Exception;
var entry = ex.Entries.Single();
//problems with ef4.1/4.2 here because of context/model in different projects.
//var databaseValues = entry.CurrentValues.Clone().ToObject();
//var clientValues = entry.Entity;
//So - if using EF 4.1/4.2 you may use this workaround
var clientValues = entry.CurrentValues.Clone().ToObject();
entry.Reload();
var databaseValues = entry.CurrentValues.ToObject();
List<string> propertyNames;
filterContext.Controller.ViewData.ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again to cause your changes to be the current saved values.");
PropertyInfo[] entityFromDbProperties = databaseValues.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance);
if (_propertyMatchingMode == PropertyMatchingMode.UseViewModelNamesToCheckEntity)
{
//We dont have access to the model here on an exception. Get the field names from modelstate:
propertyNames = filterContext.Controller.ViewData.ModelState.Keys.ToList();
}
else if (_propertyMatchingMode == PropertyMatchingMode.UseEntityFieldsOnly)
{
propertyNames = databaseValues.GetType().GetProperties(BindingFlags.Public).Select(o => o.Name).ToList();
}
else
{
filterContext.ExceptionHandled = true;
UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues);
filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData };
return;
}
UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues);
//Get all public properties of the entity that have names matching those in our modelstate.
foreach (var propertyInfo in entityFromDbProperties)
{
//If this value is not in the ModelState values, don't compare it as we don't want
//to attempt to emit model errors for fields that don't exist.
//Compare db value to the current value from the entity we posted.
if (propertyNames.Contains(propertyInfo.Name))
{
if (propertyInfo.GetValue(databaseValues, null) != propertyInfo.GetValue(clientValues, null))
{
var currentValue = propertyInfo.GetValue(databaseValues, null);
if (currentValue == null || string.IsNullOrEmpty(currentValue.ToString()))
{
currentValue = "Empty";
}
filterContext.Controller.ViewData.ModelState.AddModelError(propertyInfo.Name, "Current value: "
+ currentValue);
}
}
//TODO: hmm.... how can we only check values applicable to the model/modelstate rather than the entity we saved?
//The problem here is we may only have a few fields used in the viewmodel, but many in the entity
//so we could have a problem here with that.
}
filterContext.ExceptionHandled = true;
filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData };
}
}
public HandleConcurrencyException()
{
_propertyMatchingMode = PropertyMatchingMode.UseViewModelNamesToCheckEntity;
}
public HandleConcurrencyException(PropertyMatchingMode propertyMatchingMode)
{
_propertyMatchingMode = propertyMatchingMode;
}
/// <summary>
/// Searches the database loaded entity values for a field that has a [Timestamp] attribute.
/// It then writes a string version of ther byte[] timestamp out to modelstate, assuming
/// we have a timestamp field on the page that caused the concurrency exception.
/// </summary>
/// <param name="filterContext"></param>
/// <param name="entityFromDbProperties"></param>
/// <param name="databaseValues"></param>
private void UpdateTimestampField(ExceptionContext filterContext, PropertyInfo[] entityFromDbProperties, object databaseValues)
{
foreach (var propertyInfo in entityFromDbProperties)
{
var attributes = propertyInfo.GetCustomAttributesData();
//If this is a timestamp field, we need to set the current value.
foreach (CustomAttributeData attr in attributes)
{
if (typeof(System.ComponentModel.DataAnnotations.TimestampAttribute).IsAssignableFrom(attr.Constructor.DeclaringType))
{
//This currently works only with byte[] timestamps. You can use dates as timestampts, but support is not provided here.
byte[] timestampValue = (byte[])propertyInfo.GetValue(databaseValues, null);
//we've found the timestamp. Add it to the model.
filterContext.Controller.ViewData.ModelState.Add(propertyInfo.Name, new ModelState());
filterContext.Controller.ViewData.ModelState.SetModelValue(propertyInfo.Name,
new ValueProviderResult(Convert.ToBase64String(timestampValue), Convert.ToBase64String(timestampValue), null));
break;
}
}
}
}
}
}
Do you know why I had to change
if (propertyInfo.GetValue(databaseValues, null) != propertyInfo.GetValue(clientValues, null))
to
if (!Equals(propertyInfo.GetValue(databaseValues,null), propertyInfo.GetValue(clientValues,null)))
It was giving me false positives for anything that was not a string.
After I made that change it worked for me.
Here is the complete modified function
public void OnException(ExceptionContext filterContext)
{
if (!filterContext.ExceptionHandled && filterContext.Exception is DbUpdateConcurrencyException)
{
//Get original and current entity values
DbUpdateConcurrencyException ex = (DbUpdateConcurrencyException)filterContext.Exception;
var entry = ex.Entries.Single();
//problems with ef4.1/4.2 here because of context/model in different projects.
//var databaseValues = entry.CurrentValues.Clone().ToObject();
//var clientValues = entry.Entity;
//So - if using EF 4.1/4.2 you may use this workaround
var clientValues = entry.CurrentValues.Clone().ToObject();
entry.Reload();
var databaseValues = entry.CurrentValues.ToObject();
List<string> propertyNames;
filterContext.Controller.ViewData.ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again to cause your changes to be the current saved values.");
PropertyInfo[] entityFromDbProperties = databaseValues.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance);
if (_propertyMatchingMode == PropertyMatchingMode.UseViewModelNamesToCheckEntity)
{
//We dont have access to the model here on an exception. Get the field names from modelstate:
propertyNames = filterContext.Controller.ViewData.ModelState.Keys.ToList();
}
else if (_propertyMatchingMode == PropertyMatchingMode.UseEntityFieldsOnly)
{
propertyNames = databaseValues.GetType().GetProperties(BindingFlags.Public).Select(o => o.Name).ToList();
}
else
{
filterContext.ExceptionHandled = true;
UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues);
filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData };
return;
}
UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues);
//Get all public properties of the entity that have names matching those in our modelstate.
foreach (var propertyInfo in entityFromDbProperties)
{
//If this value is not in the ModelState values, don't compare it as we don't want
//to attempt to emit model errors for fields that don't exist.
//Compare db value to the current value from the entity we posted.
if (propertyNames.Contains(propertyInfo.Name))
{
//if (propertyInfo.GetValue(databaseValues, null) != propertyInfo.GetValue(clientValues, null))
if (!Equals(propertyInfo.GetValue(databaseValues,null), propertyInfo.GetValue(clientValues,null)))
{
var currentValue = propertyInfo.GetValue(databaseValues, null);
if (currentValue == null || string.IsNullOrEmpty(currentValue.ToString()))
{
currentValue = "Empty";
}
filterContext.Controller.ViewData.ModelState.AddModelError(propertyInfo.Name, "Database value: "
+ currentValue);
}
}
//TODO: hmm.... how can we only check values applicable to the model/modelstate rather than the entity we saved?
//The problem here is we may only have a few fields used in the viewmodel, but many in the entity
//so we could have a problem here with that.
}
filterContext.ExceptionHandled = true;
filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData };
}
}

Visual Studio 2010 Extensions

I'm writing my own abstract extension for Visual Studio 2010, it makes similary functionality as Ook Language Integration. I have a question, is it possibly to mix my own AutoCompletion with standart C++ autocompletion of VS? How to do it? Is in need to use libraries of VS and call some methods?
This is a very good example about adding features to C# intellisense.
First of all you should capture the completionSession and use it.
Like this snippet, but in C++
[Export(typeof(IIntellisensePresenterProvider))]
[ContentType("text")]
[Order(Before = "Default Completion Presenter")]
[Name("Object Intellisense Presenter")]
internal class IntellisensePresenterProvider : IIntellisensePresenterProvider
{
[Import(typeof(SVsServiceProvider))]
IServiceProvider ServiceProvider { get; set; }
#region Try Create Intellisense Presenter
#region Documentation
/// <summary>
/// Inject the IntelliSense presenter
/// </summary>
/// <param name="session"></param>
/// <returns></returns>
#endregion // Documentation
public IIntellisensePresenter TryCreateIntellisensePresenter(IIntellisenseSession session)
{
#region Validation (is C#)
const string CSHARP_CONTENT = "CSharp";
if (session.TextView.TextBuffer.ContentType.TypeName != CSHARP_CONTENT)
{
return null;
}
#endregion // Validation
ICompletionSession completionSession = session as ICompletionSession;
if (completionSession != null)
{
var presenter = new IntelliSenseViewModel(ServiceProvider, completionSession);
return presenter;
}
return null;
}
#endregion // Try Create Intellisense Presenter
}
Hope helps!

Resources