How can i Create a Static component in visual studio? - visual-studio-2010

am doing some app that has a lots of forms and some components have to access some componets from another form ....when i make my richtextbox public and try to access it from somewhere else it says thread safe error bla bla ...so i made that text box static so that there would be only object that belong to the class and i can access it like this.
Form1.richTextBox.Text
and this works fine but the problem is every time i add a new component to the winform my static object become non static and all my direct access to the objects becomes error.
my question is how can i make visual studio to stop modifying my code(design code) ? or safely access objects from other form without circular dependency?

From your comment "try to access it from somewhere else it says thread safe error"
I believe the issue is a cross thread operation. Is that "somewhere else" executing on a background/worker thread? ie. NOT the thread on which your richtextbox was instantiated.
If so, you MUST test the InvokeRequired property.
From MSDN:
"Gets a value indicating whether the caller must call an invoke method when making method calls to the control because the caller is on a different thread than the one the control was created on."
BTW: Even though you see a C# object (richtextbox), it is merely a facade over a Windows Handle. So, Visual Studio's behavior is correct. A control can have ONLY one parent(ie the Window) If you 'think' you need a static richtextbox then you should rethink your design.

Try to create some static element like String myStatic and access to this element from other form. In place where you need update this element use some method like
void UpdateMyStatic() {
myStatic = richTextBox.Text;
}

Related

Xamarin Async Constructor

For my application I need to fetch some data asynchronously and do some initialization for each page. Unfortunately, a constructor does not allow me to make asynchronous calls. I followed this article and put all of my code into the OnAppearing method. However, since then I ran into multiple issues since each platform handles the event a little bit differently. For example, I have pages where you can take pictures, on iOS the OnAppearing is called again every time after the camera is closed while Android doesn't. It doesn't seem like a reliable method for my needs, which is also described here:
Calls to the OnDisappearing and OnAppearing overrides cannot be treated as guaranteed indications of page navigation. For example, on iOS, the OnDisappearing override is called on the active page when the application terminates.
I am searching for a method/way where I can perform my own initialization. The constructor would be perfect for that but I cannot perform anything asynchronously in there. Please do not provide me with any work arounds, I am searching for a solution that is the "recommended" way or maybe someone with a lot of experience can tell me what they are doing. (I also don't want to .Wait() or .Result as it will lock my app)
You can use Stephen Cleary's excellent NotifyTaskCompletion class.
You can read more how it works and what to do/don't in these cases in Microsoft's excellent Async Programming : Patterns for Asynchronous MVVM Applications: Data Binding. The highlights of this topics are:
Let’s walk through the core method
NotifyTaskCompletion.WatchTaskAsync. This method takes a task
representing the asynchronous operation, and (asynchronously) waits
for it to complete. Note that the await does not use
ConfigureAwait(false); I want to return to the UI context before
raising the PropertyChanged notifications. This method violates a
common coding guideline here: It has an empty general catch clause. In
this case, though, that’s exactly what I want. I don’t want to
propagate exceptions directly back to the main UI loop; I want to
capture any exceptions and set properties so that the error handling
is done via data binding. When the task completes, the type raises
PropertyChanged notifications for all the appropriate properties.
A sample usage of it:
public class MainViewModel
{
public MainViewModel()
{
UrlByteCount = new NotifyTaskCompletion<int>(
MyStaticService.CountBytesInUrlAsync("http://www.example.com"));
}
public NotifyTaskCompletion<int> UrlByteCount { get; private set; }
}
Here, the demo is about binding the returned asynchronous value to some bindable property, but of course you can you is without any return value (for simple data loading).
This may be too simple to say, but you CAN run asynchronous tasks in the constructor. Just wrap it in an anonymous Task.
public MyConstructor() {
Task.Run(async () => {
<Your code>
}
}
Be careful when doing this though as you can get into resource conflict issues if you accidentally open the page twice.
Another thing I like to do is use an _isInit flag, which indicates a first time use, and then never again.

Is it bad to use ViewModelLocator to Grab other VM's for use in another Vm?

I am using MVVM light and figured out since that the ViewModelLocator can be used to grab any view model and thus I can use it to grab values.
I been doing something like this
public class ViewModel1
{
public ViewModel1()
{
var vm2 = new ViewModelLocator().ViewModel2;
string name = vm2.Name;
}
}
This way if I need to go between views I can easily get other values. I am not sure if this would be best practice though(it seems so convenient makes me wonder if it is bad practice lol) as I know there is some messenger class thing and not sue if that is the way I should be doing it.
Edit
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<ViewModel1>();
SimpleIoc.Default.Register<ViewModel2>();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public ViewModel1 ViewModel1
{
get
{
return ServiceLocator.Current.GetInstance<ViewModel1 >();
}
}
Edit
Here is a scenario that I am trying to solve.
I have a view that you add price and store name to. When you click on the textbox for store name you are transferred to another view. This view has a textbox that you type the store you are looking for, as you type a select list get populated with all the possible matches and information about that store.
The user then chooses the store they want. They are transferred back to the view where they "add the price", now the store name is filled in also.
If they hit "add" button it takes the price, the store name, and the barcode(this came from the view BEFORE "add price view") and sends to a server.
So as you can see I need data from different views.
I'm trying to understand what your scenario is. In the MVVMlight forum, you added the following context to this question:
"I have some data that needs to be passed to multiple screens and possibly back again."
For passing data between VMs, I would also - as Matt above - use the Messenger class of MVVMLight as long as it is "fire and forget". But it is the "possibly back again" comment that sounds tricky.
I can imagine some scenarios where this can be needed. Eg. a wizard interface. In such a case I would model the data that the wizard is responsible for collecting and then bind all Views to the same VM, representing that model object.
But that's just one case.
So maybe if you could provide a little more context, I would be happy to try and help.
Yes, you can do this, in as much as the code will work but there is a big potential issue you may run into in the future.
One of the strong arguments for using the MVVM pattern is that it makes it easier to write code that can be easily tested.
With you're above code you can't test ViewModel1 without also having ViewModelLocator and ViewModel2. May be that's not too much of a bad thing in and of itself but you've set a precedent that this type of strong coupling of classes is acceptable. What happens, in the future, when you
From a testing perspective you would probably benefit from being able to inject your dependencies. This means passing, to the constructor--typically, the external objects of information you need.
This could mean you have a constructor like this:
public ViewModel1(string vm2Name)
{
string name = vm2Name;
}
that you call like this:
var vm1 = new ViewModel1(ViewModelLocator.ViewModel2.name);
There are few other issues you may want to consider also.
You're also creating a new ViewModelLocator to access one of it's properties. You probably already have an instance of the locator defined at the application level. You're creating more work for yourself (and the processor) if you're newing up additional, unnecessary instances.
Do you really need a complete instance of ViewModel2 if all you need is the name? Avoid creating and passing more than you need to.
Update
If you capture the store in the first view/vm then why not pass that (ID &/or Name) to the second VM from the second view? The second VM can then send that to the server with the data captured in the second view.
Another approach may be to just use one viewmodel for both views. This may make your whole problem go away.
If you have properties in 1 view or view model that need to be accessed by a second (or additional) views or view models, I'd recommend creating a new class to store these shared properties and then injecting this class into each view model (or accessing it via the locator). See my answer here... Two views - one ViewModel
Here is some sample code still using the SimpleIoc
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<IMyClass, MyClass>();
}
public IMyClass MyClassInstance
{
get{ return ServiceLocator.Current.GetInstance<IMyClass>();}
}
Here is a review of SimpleIOC - how to use MVVMLight SimpleIoc?
However, as I mentioned in my comments, I changed to use the Autofac container so that my supporting/shared classes could be injected into multiple view models. This way I did not need to instantiate the Locator to access the shared class. I believe this is a cleaner solution.
This is how I registered MyClass and ViewModels with the Autofac container-
var builder = new ContainerBuilder();
var myClass = new MyClass();
builder.RegisterInstance(myClass);
builder.RegisterType<ViewModel1>();
builder.RegisterType<ViewModel2>();
_container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(_container));
Then each ViewModel (ViewModel1, ViewModel2) that require an instance of MyClass just add that as a constructor parameter as I linked initially.
MyClass will implement PropertyChanged as necessary for its properties.
Ok, my shot at an answer for your original question first is: Yes, I think it is bad to access one VM from another VM, at least in the way it is done in the code example of this question. For the same reasons that Matt is getting at - maintainability and testability. By "newing up" another ViewModelLocator in this way you hardcode a dependency into your view model.
So one way to avoid that is to consider Dependency Injection. This will make your dependencies explicit while keeping things testable. Another option is to use the Messenger class of MVVMLight that you also mention.
In order to write maintainable and testable code in the context of MVVM, ViewModels should be as loosely coupled as possible. This is where the Messenger of MVVMLight can help. Here's a quote from Laurent on what Messenger class was intended for:
I use it where decoupled communication must take place. Typically I use it between VM and view, and between VM and VM. Strictly speaking you can use it in multiple places, but I always recommend people to be careful with it. It is a powerful tool, but because of the very loose coupling, it is easy to lose the overview on what you are doing. Use it where it makes sense, but don't replace all your events and commands with messages.
So, to answer the more specific scenario you mention, where one view pops up another "store selection" view and the latter must set the current store when returning back to the first view, this is one way to do it (the "Messenger way"):
1) On the first view, use EventToCommand from MVVMLight on the TextBox in the first view to bind the desired event (eg. GotFocus) to a command exposed by the view model. Could be eg. named OpenStoreSelectorCommand.
2) The OpenStoreSelectorCommand uses the Messenger to send a message, requesting that the Store Selector dialog should be opened. The StoreSelectorView (the pop-up view) subscribes to this message (registers with the Messenger for that type of message) and opens the dialog.
3) When the view closes with a new store selected, it uses the Messenger once again to publish a message that the current store has changed. The main view model subscribes to this message and can take whatever action it needs when it receives the message. Eg. update a CurrentStore property, which is bound to a field on the main view.
You may argue that this is a lot of messaging back and forth, but it keeps the view models and views decoupled and does not require a lot code.
That's one approach. That may be "old style" as Matt is hinting, but it will work, and is better than creating hard dependencies.
A service-based approach:
For a more service-based approach take a look at this recent MSDN Magazine article, written by the inventor of MVVMLight. It gives code examples of both approaches: The Messenger approach and a DialogService-based approach. It does not, however, go into details on how you get values back from a dialog window.
That issue is tackled, without relying on the Messenger, in this article. Note the IModalDialogService interface:
public interface IModalDialogService
{
void ShowDialog<TViewModel>(IModalWindow view, TViewModel viewModel, Action<TViewModel> onDialogClose);
void ShowDialog<TDialogViewModel>(IModalWindow view, TDialogViewModel viewModel);
}
The first overload has an Action delegate parameter that is attached as the event handler for the Close event of the dialog. The parameter TViewModel for the delegate is set as the DataContext of the dialog window. The end result is that the view model that caused the dialog to be shown initially, can access the view model of the (updated) dialog when the dialog closes.
I hope that helps you further!

Registering Window Class

I guess my question is relatively easy for those of you who spent time dealing with Win32 API.
So my question is:
After initializing a WNDCLASSEX instance we need to "register" it using the "RegisterClassEx" function, why? Why do we do that? What's the meaning of this registration and in what cases I need to register things?
The ATOM returned by RegisterClassEx uniquely identifies your "window class" which can then be referred to in other windows APIs. [MSDN]
Effectively it is a hash so as to reduce the amount of data processed each time a window is created or looked for. It does also mean that multiple windows with same features can be easily created and identified.
I was addressing the practical reasons above. Hans Passant's answer correctly explains this is the OO class concept provided for C. Further MSDN example.
The word Class in the function name is significant. When you write code in an object oriented language, like C++, Delphi, Java or C# etcetera, then you use the class keyword to create objects that have behavior. But the winapi was designed to be used from C, a language that doesn't have such functionality. The RegisterClassEx() function is an emulation of that, it lets you create a window that "derives" its behavior from a named class, behavior that you can override. With every window that you create using that class name behaving identically.
The WNDCLASSEX structure you pass gives a window its default behavior. The most significant members of this structure are:
lpszClassName. That's the equivalent of the C++ class name. You can later call CreateWindowEx() and pass that name to get a window that behaves a certain way. Windows itself calls RegisterClassEx() to register several of its built-in window classes that you then can readily re-use in your own code. "EDIT", "BUTTON" and "LISTBOX" are good examples of that.
lpfnWndProc. This is what gives a window class its specific default behavior. The address of its window procedure that implement message handlers for specific messages. You can further customize the default behavior, in other words "derive" your own class from the base class, by specifying another window procedure in the CreateWindowEx() call. Such a window procedure must always call DefWindowProc(), the equivalent of calling the base class method. Or in other words, a window has one virtual method.
hIcon, etcetera. These are the equivalent of properties of the base class, they set default values that affect the default message handlers. Helping you to keep your window procedure simple. It is for example rarely necessary to write a message handler for WM_ERASEBKGND, the hbrBackground member sets the default background for a window.
Windows requires you to call RegisterClassEx() even if you don't plan on re-using a window. Which is by far the most common usage of the function in your own code. You don't start to really take advantage of it until you write a library that implements controls, windows that other code can use. Like "EDIT".

COM object that has been separated from its underlying RCW cannot be used

I am trying to use the OpcRcw.da.dll. If I interop this dll inside a test console project everything works, but if I build dll project to do my interop gymnastic and ref my library into my console project I am getting this error:
COM object that has been separated from its underlying RCW cannot be used.
What need to be done to a class lib project to not kill the RCW ref?
This can happen for a few reasons, the big ones I know of are below.
Event Handlers Without Strong References to the Delegate
A caller subscribes to an event on the com object without keeping a strong reference to the callback delegate. Here is an example of how to do this correctly and how to not do it:
The reason for this is a strong reference needs to be kept to the delegate, if it goes out of scope, the wrapper will release the reference count for the interface and bad things will happen.
public class SomeClass
{
private Interop.ComObjectWrapper comObject;
private event ComEventHandler comEventHandler;
public SomeClass()
{
comObject = new Interop.ComObjectWrapper();
// NO - BAD!
comObject.SomeEvent += new ComEventHandler(EventCallback);
// YES - GOOD!
comEventHandler = new ComEventHandler(EventCallback);
comObject.SomeEvent += comEventHandler
}
public void EventCallback()
{
// DO WORK
}
}
Calls to a disposed Runtime Callable Wrapper
The wrapper has been disposed and calls are being made after it has been disposed. A common way this can happen is if a control is using an activex control or COM object and the controls Dispose() is called out of order.
A form gets Close() called.
System.Windows.Forms.Close() will call Dispose()
Your forms virtual Dispose() will be called which hopefully calls base.Dispose() somewhere. Systems.Windows.Forms.Dispose() will release all COM objects and event syncs on the form, even from child controls.
If the control that owns a com object is explicitly disposed after base.Dispose() and if it calls any methods on it's COM object, these will now fail and you will get the error “COM object that has been separated from its underlying RCW cannot be used”.
Debugging Steps
A good way to debug this issue is to do the following:
Write a class that inherits from the Interop class (otherwise known as the runtime callable wrapper or RCW).
Override DetachEventSink
Override Dispose
Call your new class instead of calling the interop class directly
Add breakpoint to DetachEventSink and Dispose
See who is calling these methods out of order
One other thing
This isn't related to this issue but while we are on the topic, unless you know otherwise, always remember to check that the thread your COM objects are being used from are marked STA. You can do this by breaking in the debugger and checking the value returned from:
Thread.CurrentThread.GetApartmentState();
It's somewhat hard to tell what your actual application is doing, but it sounds like you may be instantiating the COM object and then attempting to access it from another thread, perhaps in a Timer.Elapsed event. If your application is multithreaded, you need to instantiate the COM object within each thread you will be using it in.

When must I set a variable to "Nothing" in VB6?

In one of my VB6 forms, I create several other Form objects and store them in member variables.
Private m_frm1 as MyForm
Private m_frm2 as MyForm
// Later...
Set m_frm1 = New MyForm
Set m_frm2 = New MyForm
I notice that I'm leaking memory whenever this (parent) form is created and destroyed. Is it necessary for me to assign these member variables to Nothing in Form_Unload()?
In general, when is that required?
SOLVED: This particular memory leak was fixed when I did an Unload on the forms in question, not when I set the form to Nothing. I managed to remove a few other memory leaks by explicitly setting some instances of Class Modules to Nothing, as well.
Actually, VB6 implements RAII just like C++ meaning that locally declared references automatically get set to Nothing at the end of a block. Similarly, it should automatically reset member class variables after executing Class_Terminate. However, there have been several reports that this is not done reliably. I don't remember any rigorous test but it has always been best practice to reset member variables manually.
#Matt Dillard - Did setting these to nothing fix your memory leak?
VB6 doesn't have a formal garbage collector, more along the lines of what #Konrad Rudolph said.
Actually calling unload on your forms seems to me to be the best way to ensure that the main form is cleaned up and that each subform cleans up their actions.
I tested this with a blank project and two blank forms.
Private Sub Form_Load()
Dim frm As Form2
Set frm = New Form2
frm.Show
Set frm = Nothing
End Sub
After running both forms are left visible. setting frm to nothing did well... nothing.
After settign frm to nothing, the only handle open to this form is via the reference.
Unload Forms(1)
Am I seeing the problem correctly?
Josh
Objects in VB have reference counting. This means that an object keeps a count of how many other object variables hold a reference to it. When there are no references to the object, the object is garbage collected (eventually). This process is part of the COM specification.
Usually, when a locally instantiated object goes out of scope (i.e. exits the sub), its reference count goes down by one, in other words the variable referencing the object is destroyed. So in most instances you won't need to explicitly set an object equal to Nothing on exiting a Sub.
In all other instances you must explicitly set an object variable to Nothing, in order to decrease its reference count (by one). Setting an object variable to Nothing, will not necessarily destroy the object, you must set ALL references to Nothing. This problem can become particularly acute with recursive data structures.
Another gotcha, is when using the New keyword in an object variable declaration. An object is only created on first use, not at the point where the New keyword is used. Using the New keyword in the declaration will re-create the object on first use every time its reference count goes to zero. So setting an object to Nothing may destroy it, but the object will automatically be recreated if referenced again. Ideally you should not declare using the New keyword, but by using the New operator which doesn't have this resurrection behaviour.
#Martin
VB6 had a "With/End With" statement that worked "like" the Using() statement in C#.NET. And of course, the less global things you have, the better for you.
With/End With does not working like the Using statement, it doesn't "Dispose" at the end of the statement.
With/End With works in VB 6 just like it does in VB.Net, it is basically a way to shortcut object properties/methods call. e.g.
With aCustomer
.FirstName = "John"
.LastName = "Smith"
End With
Strictly speaking never, but it gives the garbage collector a strong hint to clean things up.
As a rule: do it every time you're done with an object that you've created.
Setting a VB6 reference to Nothing, decreases the refecences count that VB has for that object. If and only if the count is zero, then the object will be destroyed.
Don't think that just because you set to Nothing it will be "garbage collected" like in .NET
VB6 uses a reference counter.
You are encouraged to set to "Nothing" instanciated objects that make referece to C/C++ code and stuff like that. It's been a long time since I touched VB6, but I remember setting files and resources to nothing.
In either case it won't hurt (if it was Nothing already), but that doesn't mean that the object will be destroyed.
VB6 had a "With/End With" statement that worked "like" the Using() statement in C#.NET. And of course, the less global things you have, the better for you.
Remember that, in either case, sometimes creating a large object is more expensive than keeping a reference alive and reusing it.
I had a problem similar to this a while back. I seem to think it would also prevent the app from closing, but it may be applicable here.
I pulled up the old code and it looks something like:
Dim y As Long
For y = 0 To Forms.Count -1
Unload Forms(x)
Next
It may be safer to Unload the m_frm1. and not just set it to nothing.
One important point that hasn't yet been mentioned here is that setting an object reference to Nothing will cause the object's destructor to run (Class_Terminate if the class was written in VB) if there are no other references to the object (reference count is zero).
In some cases, especially when using a RAII pattern, the termination code can execute code that can raise an error. I believe this is the case with some of the ADODB classes. Another example is a class that encapsulates file i/o - the code in Class_Terminate might attempt to flush and close the file if it's still open, which can raise an error.
So it's important to be aware that setting an object reference to Nothing can raise an error, and deal with it accordingly (exactly how will depend on your application - for example you might ignore such errors by inserting "On Error Resume Next" just before "Set ... = Nothing").

Resources