Best way to do the runtime UI changes on User Control? - c#

I am new to the .net and I am working on the some functionality in office that is as below
Jobs.aspx.cs
protected void gvActionItems_RowEditing(object sender, GridViewEditEventArgs e)
{
//setting the value of the user control property
}
JobUserControl.ascx.cs
public int _usrcontrolproperty
{
get{return _usrcontrolproperty;}
set{
//depending on the value of the property fetch the data from the database and binding those data on the user controls FormView
}
}
protected void fvJob_DataBound(object sender, EventArgs e)
{
//Making the dynamic UI changes that is setting properties of controls depending upon the values of binding data
}
This is how i did the required UI changes in databound event of form view, but one of senior says 'It's bad architectural code design it has extra memory issue and make the UI changes in the _usrcontrolproperty set method after the data bind.'. So i want to know
1) Is this really bad architectural code ? If bad then why ?
2) And if my seniors way is bad then also Why ?
Because i thought the UI changes should done at the the time of the binding the data

If your senior cannot backup his/her claims.. then he/she isn't really someone you should try learning from. I'm not sure what the "memory issue" is that he/she is referring to, however it's hard to tell with your stripped down code.
That being said, I would reconsider databinding in a property set purely because you open yourself up to "gotcha's" later down the track when people start setting this property.
Instead, I would have a Refresh() method. Therefore, the calling code would be:
UserControl.Property = value;
UserControl.RefreshData();
This gives the calling API the option of refreshing at that point or deferring the decision.

I am with the #Simon on this one but I would have a RefreshData(value) method. Therefore, the calling code would be:
UserControl.RefreshData(value);
This gives the calling API the option of refreshing at that point or deferring the decision.
An in this method you can use as ,
Public static RefreshData(<datatype>data)
{
//Assign the value to the property
//Get the data from database
//Bind the data
}
And you can also make your property private or protected if you don't want to expose the property to other classes.

Related

How to create a static instance of a page at application startup time?

I currently have a MainWindow that acts as a frame to navigate to other pages in my solution. The problem is, i require one of my pages to be instantiated for the entire duration of my application instead of every time when i navigate to a page, that page gets re-instantiated. I have tried the KeepAlive='true' property for my page but it did not work.
I would like to know if theres a way to implement "this static instance of a page" method for my codes. Thanks. (p.s im not looking or planning to implement the MVVM approach)
public MainWindow()
{
InitializeComponent();
//Instanciate ApiStartup class and Initialize the HTTPClient
ApiStartup.InitializeClient();
Application.Current.MainWindow = this;
Loaded += OnMainWindowLoaded;
}
private void OnMainWindowLoaded(object sender, RoutedEventArgs e)
{
ChangeView(new DetectionPage());
}
public void ChangeView(Page view)
{
MainFrame.NavigationService.Navigate(view);
}
private void quiz_Click(object sender, MouseButtonEventArgs e)
{
var mainWindow = (MainWindow)Application.Current.MainWindow;
mainWindow?.ChangeView(new DetectionPage());
}
If you want to use static value for use in entire application from start to end then you can mention it in app.config file. And easily you can use like ((App)Application.current).KeepAlive in your any xaml file.
A page has the keepalive property.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.page.keepalive?view=netframework-4.8
You may set that to true on whichever page you like.
When you later use navigation methods to navigate to that url, the first instance of the page will be returned.
If that doesn't suit for whatever reason you could cache instances of pages using a dictionary with key type and value page (instance). Then implement some logic decides which pages you do or do not cache in there.
You said you don't want to use mvvm but I think it best to at least mention what almost everyone else does. For other people who intend working in a team then MVVM will be expected and hence for other people reading:
Since pages and frames come with a journal and memory overheads that are often undesirable, most teams (I have encountered) use usercontrols rather than pages. These are presented via a contentcontrol. You can set content to a usercontrol but most teams use viewmodel first. State that matters is bound and templated from an instance of a viewmodel. To retain state between "navigations" a reference to the viewmodel is retained - which is almost guaranteed to be way lighter on memory than any sort of view.

Databinding to object - How to cancel datasource changes

Here is the scenario:
I have an Edit Dialog form with a BindingSource and some data bound text boxes on it:
I pass an entity to the form constructor and it gets loaded into BindingSource.DataSource which causes the data bound controls to show the values of properties.
The problem is as the user edits the values in TextBox controls and Validating events get passed, the data source gets changed though it is not applying to DB but it still can confuses the user as he sees the edited values on the List Form, till next application restart.
so the question is: How to prevent binding source from reflecting changes instantly or how to roll them back?
I inherited the binding source and created a new binding source like this:
public class SuperBindingSource:BindingSource
{
#region Properties
public object DataSourceBeforeChange { get; private set; }
#endregion
#region Methods
public void ResetChanges()
{
this.DataSource = this.DataSourceBeforeChange;
}
#endregion
protected override void OnDataSourceChanged(EventArgs e)
{
base.OnDataSourceChanged(e);
DataSourceBeforeChange=this.DataSource.DeepClone();
}
}
Though I am not sure if it is a good approach.
As an option, when setting up data-bindings, you can set them to update data source never.
Then at the point that you want to apply changes, for example when pressing OK button, you can set data-bindings to update data source on property change and then call end edit method of the binding source.
For Cancel button, you don't need to do anything, because the data source is not updated.
Example
In form load event:
this.BindingContext[bindingSource].Bindings.Cast<Binding>().ToList()
.ForEach(b=>b.DataSourceUpdateMode= DataSourceUpdateMode.Never);
When pressing OK:
this.BindingContext[productBindingSource].Bindings.Cast<Binding>().ToList()
.ForEach(b => b.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged);
productBindingSource.EndEdit();
You can download/clone the full source code:
r-aghaei/SuspendDataBindingExample
You can use the SuspendBinding method after the values are loaded.
After that the values should not update the source until you call ResumeBinding:
SuspendBinding and ResumeBinding are two methods that allow the temporary suspension and resumption of data binding in a simple-binding scenario. You would typically suspend data binding if the user must be allowed to make several edits to data fields before validation occurs. For example, if one field must be changed in accordance with a second, but where validating the first field would cause the second field to be in error.
According to the documentation you should be able to use this with your textboxes. If the user clicks Ok to save the values you resume the binding and if he cancels you don't.

DataGridView DataSource: Slow Assignment

I have inherited a form and have been tasked with speeding it up. Basically, it is a form which makes a WCF call to a service for some data, and then displays the data in a DataGridView.
I originally thought the bottleneck was the WCF call, so I moved that to a BackgroundWorker, to stop the UI from freezing up.
That helped a little bit, but it turns out that the bottleneck is actually this line:
DumpInfoGrid.DataSource = dumpGridBinding;
where the data retrieved from the WCF is assigned to the DataSource property.
The code basically boils down to this:
private BackgroundWorker dataGatherer;
dataGatherer.DoWork += dataGatherer_DoWork;
dataGatherer.RunWorkerCompleted += dataGatherer_RunWorkerCompleted;
private void dataGatherer_DoWork(object sender, DoWorkEventArgs e)
{
dumpGridBinding = WCF.GetDataFromService();
}
private void dataGatherer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DumpInfoGrid.DataSource = dumpGridBinding;
}
Is there anything I can do to speed this up? Or any part I can move to the BackgroundWorker ? The assignment freezes the UI for far too long.
One possible solution for this would be to use FastDataGridView (or FastDataListView) which is found in ObjectListView, which greatly improves the speed of the DataGridView control by not attempting to process all the records at one time.
Another solution would be to page the DataGridView you currently have, spreading out the load time across the pages as you use them as seen here
You could use virtual mode -
MSDN: http://msdn.microsoft.com/en-us/library/15a31akc.aspx
This mode shows just the rows the user is looking at through the viewable region - you only load the rows actually being viewed - which is fast.
You handle the CellValueNeeded event and provide data from your list when the user scrolls through the list. Tex example shows you how to do that, but it's easy to write a linq statement to skip, take whatever is requested from your datasource (returned from the WCF service).

How do you send data from a form to a class?

I have a Class named Testing and a Form called TitleScreen. In TitleScreen I have a textBox1 who's text I would like to be passed to a Class and then pass it back to my Form into a textBox2.
I know how to do only the basics in C# so if you try and make it simple as possible.
In your Class:
public class Class1
{
public static string SeparateName(string fullName)
{
string[] wordsInText = fullName.Split(' ');
return wordsInText[0];
}
}
In your Form:
private void button1_Click(object sender, System.EventArgs e)
{
textBox2.Text = Class1.SeparateName(textBox1.Text);
}
"I highly recommend that you read a book or tutorial that targets new users, otherwise there will be holes in your understanding of the language and the frameworks."
It sounds like you want to perform an operation on the textbox's value and then print the result in another textbox.
You can write a method (function) that accepts an argument of type String and perform the operation in that method. The method can then set the Text property of the textbox to the result.
If you're asking how to input code in a winforms project, you can double-click the background of the form to reach its code. (At least in Visual Studio)
If you don't know how to do the above suggestions, I highly recommend that you read a book or tutorial that targets new users, otherwise there will be holes in your understanding of the language and the frameworks.
I would suggest you want to look at the concept of data binding, whereby you bind the controls on your forms to the properties of the underlying objects (instances of your classes).
Binding removes the need to write code to cross-load the data from the class into the form and back again, instead you can then say "text box 1 is bound to this property of my class". Then, when you update the value of the textbox the data is automatically placed into the chosen property of your class instance. Typically you then have a save button that calls a save method on your class to persist the data to your data store (database or whatever).
It is perfectly reasonable to bind more than one control on your form to the same property on your underlying class, so in your example you can bind both textBox1 and textBox2 to the same property on your class. Then, once you've implemented databinding, when you change the value in textBox1, the value will automatically be reflected in textBox2, either on each keystroke or when the field is validated (typically when you move focus to another control).
This is the microsoft documentation on Winforms binding which covers everything you need: https://msdn.microsoft.com/en-us/library/ef2xyb33(v=vs.110).aspx

Databinding best practice for User Controls in Web Forms

I was wondering about some best practices for data binding in web forms.
For example we have a control:
public partial class MyUserControl : UserControl
{
public override void DataBind()
{
//#1
base.DataBind();
//#2
}
}
If we wanted that control to bind its data automatically we would do something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.DataBind();
}
}
In the first section of code if we do our data binding before the call to base.DataBind() (#1) then that means that, if for example we databind a ListView, we don't have to call ListView.DataBind() because when we call base.DataBind() on our control it recursively calls DataBind on all child controls. Also, we won't have access to any of the properties of the control that were assigned to it using the data binding code blocks <%# %>
If we do our binding on our controls after base.DataBind() (#2) then this means that DataBind is called on these controls twice. Once when base.DataBind() is called, and the second time when we are forced to call control.DataBind().
Does anyone know of some sort of pattern I can follow here that I don't know about?
Am I making any sense here?
What am I doing wrong?
EDIT:
Looking at this page:
http://msdn.microsoft.com/en-us/library/w5e5992d.aspx
Use this method to bind data from a
source to a server control. This
method is commonly used after
retrieving a data set through a
database query. The method is
primarily used by control developers;
most controls perform data binding
automatically.
It appears that best practice is to bind controls data automatically. Databinding is for when we explicitly set a data source.
I've encountered problems previously, when pages become complex and you are relying on user controls binding their own data in the page load event. This has resulted in some long debugging sessions, as you can't be guaranteed exactly when this page load event in the control will fire.
Now, that said, these pages weren't too well designed, and we shouldn't have run into this problem, but I prefer to stick with the explicit and have my page tell the child controls when to do their thing - you may wish to avoid calling base.DataBind and do it explicitly instead - you may also wish to not override the DataBind method in this way and instead call the method on your control by another name.

Categories