I'm writing a winforms application in C# (.NET 4.0, using EntityFramework).
I wanted to add a calculated property to an entity, which I did using a partial class. I can access new property from code, but not from designer (datasource, edmx, datagridview, ...). My datagridview is bound to a entity binding source (e.g. employeeBindingSource).
I want to add my calculated property (from partial class) to datagridview as a read-only column. The only solution that I found so far is way to messy for me ( Properties in partial class not appearing in Data Sources window! ). I'd much rather programmatically add the column.
How should I approach this?
Thank you for your time and answers.
What I did was to normally design the datagridview in designer, as much as possible (all columns except for those from partial classes). Then in my usercontrol (or form or whatever you have) constructor:
//in constructor
datagridview.AutoGenerateColumns = true;
Then in in my load event of my usercontrol I hide unwanted columns that I got because I set dgv.AutoGenerateColumns = true; And also modify header text (or whatever you need) of the column from partial class property.
//load event
employeeDataGridView.Columns[11].Visible = false;
employeeDataGridView.Columns[12].HeaderText = "Partial class prop";
I hope it will help someone.
Related
I am creating a DataGridView inherited control that performs some stylizations and also adds a number of columns. The problem is that when this control is added to another form, the designer sees that the Columns property does not match its default value and so adds column generation to the designer in the new form.
To illustrate the problem. Take the following control:
class CustomDataGridView : DataGridView
{
public CustomDataGridView()
{
Columns.Clear();
Columns.Add("Column", "Header");
}
}
The Columns.Clear() is unnecessary - it's just there to illustrate that the problem is not the constructor. Anyhow, add the control it to a form. Cause the form UI to reload (by e.g. resizing the datagridview) and the designer ends up constantly adding a new column. I've tried a variety of ideas with no result. I attempted to hide the columns property from the designer, but unfortunately as it's not virtual that's also a no go.
Any ideas? I feel like I must be missing something simple since this is presumably a fairly common usage pattern. I could just add the columns at runtime, but ideally I'd like to keep them visible/editable in the designer.
The idea I mentioned in the question does actually seem to work fine just using not-really-hiding the property hiding:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new DataGridViewColumnCollection Columns { get => base.Columns; }
That solves all the issues of wanting to be able to see and interact with the columns in the designer and since the columns in this control are not intended to be modified it's acceptableish - but is there a way to actually add columns without a hack like this?
In great need help with the strange binding problem with regards to Winform UserControls.
Its like this.
Have a form with a UserControl
UserControl has a System.Windows.Forms.BindingSource control
BindingSource has a DataSource set to an entity POCO type at design time.
UserControl has controls that are bound to properties on the POCO class. An example: CreateDate
No problem in designer of the UserControl itself.
But entering the designer og the Form containing the UserControl, I get a designer error window with the message: "Cannot bind to the property or column CreateDate on the DataSource. Parameter name: dataMember"
In runtime I get the same error, but first when Show is called on the form. Here I can see on the stack trace that it is thrown after a CheckBinding call.
The error occurs no matter if the DataSource on the bindingSource is set or not during the creation (in constructor) or Load event on the form.
I can see that the designer sets my data source like this in the designer file: this.bindingSourceRecipe.DataSource = typeof(Data.Entities.Recipe);
I have tried so many things to solve this problem. It seems very strange as this is a dead simple form/control setup and should be a trivial use of Winforms usercontrols.
If I set the bindingSourceRecipe.DataSource at runtime to a temp. instance just after the InitializeComponent() in the form then no error occure;
InitializeComponent();
ucRecipeBaseControl.Recipe = new Recipe() { Id = 0, CreateDate = DateTime.Now, Name = "" };
So it seems that the Initialization cycle of the form/control somehow clears the binding source knowledge about its DataSource type.
This does of course not happen if a place all the user controls and BindingSource Directly on the form. Then everythings works, and it does not matter if the DataSource ever gets set to an instance of a Data entity.
Seems like a complete mystery to me, should be dead simple, and I'm kind of lost on what to do.
Any help or suggestions are highly appreciated.
BR Peter Meldgaard
Ahhh, got it nailed at last. It was caused by a mix of Winform designer behavior and my code. I was setting the binding controls datasource in a public property setter, so I could save a copy of the entity, to be able to compare the changed and the org. The thing is that when you put a control with a public property on a form, then the designer initializes this property to null inside the designer generated code. I did not know that. So everytime the usercontrol was instantiated, the DataSource got set to null, clearing the typeof(dataentity), albeit loosing the binding information.
Adding a null check in the setter, and only update datasource when value is not null fixed the issue.
I've build a base user control, BaseViewControl, it has a dataGridView and a bindingSource on it. Both have protected access modifiers. The dataViewGrids dataSource points to the base forms bindingSource.
Then I created an InheritedUserControl, ApplicationUserView, when prompted I pointed it to my UI assembly. It inherited some other arb UserControl in the same assembly so I manually changed it to inherit my BaseViewControl.
On the ApplicationUserView's bindingSource, I set the dataSource property to my ApplicationUser domain object. The dataGridView then proceeded to populate its columns with the properties in my ApplicationUser domain class in the DesignView, as expected.
Now, in an async callback from my controller object, where the view receives an IList<ApplicationUser>, i set my bindingSource.DataSource = applicationUserList.
I've confirmed that the callback gets called and that the applicationUserList has items in it, but at run time, the grid doesn't show any rows. I suspect it has something to do with the visual inheritance aspect of it all.
I've seen VS create copies of items from inherited forms onto the inheriting form as soon as you try and modify a property of an inherited item before, which has a similar effect, but this is not the case.
Any ideas what I'm doing wrong?
Thanks, HS
I have FormBase and MainForm : FormBase.
FormBase Contains a DataGridView dgv. in designer view of FormBase dgv font sizes are fine but in designer view and runtime in MainForm they are default values. why and what should I do??!
The designer for DVG doesn't support designing the control in an inherited form, a limitation of many designers of controls that were added in .NET 2.0. The Font property is an 'ambient' property, it gets the same value as the parent unless you've explicitly selected one (shown in bold in the Properties window). So either set the form's Font property to also change the DGV font or change the Font property of the DGV in the base form.
To clarify my comment: putting UI (together with DataGridView) from BaseForm in custom user control and using it separately on previously inheriting forms will surely fix the font problem.
If your base form is only "container" for commonly used controls (so you don't have to put 3 buttons, datagrid and label on every window) or defines some basic layout - go with custom user control.
Here's decent starting point if you want to explore this topic - Custom User Controls.
Have you tried this approach: http://dotnetengineer.wordpress.com/2008/06/27/visual-inheritance-using-datagridview/
Is there someway I could trigger DataSourceChanging event in DataGridView. The DataGridView has DataSourceChanged event which (I believe) after DataSource is bound to the DataGridView. I want to do some stuff before the property gets changed.
A Sample code of mine...
private void LoadGrid()
{
// I do some things like saving user settings here
DtgRefundAssign.DataSource = BLL.GetDataSource(parameter1, parameter2); //Just to illustrate
// And restore them after the datasource is bound
}
I need to do similar stuffs in many forms. Just thinking to develop a common procedure which does this, whenever the datasource is changed. The restoring part can be done using DataSourceChanged event... But which event should I handle to do the saving part ?
I haven't done this myself, but DataGridView isn't sealed so you should be able to create a new class that inherits from it. Create a new event "DataSourceChanging", then override the DataSource property's Setter so that it first raises that event, then actually sets the property on the parent class.
You'd then simply use that datagridview in place of the default one, and hook up your save logic to DataSourceChanging.
You can create a shadows/new property in the sub class using new/shadows keywords depending on whether you use c# or vb.net, since you cant override it. Use base.DataSource calls in the sub class to access the base class's property and use this.DataSource in the sub class to access the new DataSource property. :D