Add custom event in C++ WinForm to inspect native collection - winforms

I'm a learner of C++/CLI develop and recently i met a trouble about event handler.
The question is: I wanna add a custom Event in a winForm class which inherited System::Windows::Form, and the event must inspect a native collect (like std::deque). Whenever the size of the queue is changed, the event will do something.
I've tried to find the solution on MSDN already, but all i can find are custom managed ref class which is not i need.

From your question I assume that your native collection lies somewhere in native code (a library, namespace which uses only native c++...) otherwise I'd assume that you are working with this collection completely in .Net-Environment and then I'd like to ask you why not using one of the .net collections?
If my assumption is right and the collection lies in native code than I don't know how you could achieve this communication directly. I'm programming in C++/CLI for a while now and didn't see a way how to create an "event" in native code where .Net code reacts to.
But I would suggest to use the observer-pattern or something similar which works almost as an event. To not mix native and .Net code all over your project I recommend to make a special observer class (your observer) which can be used by native code (your subject) without bringing in .Net code. It also knows the .Net Code (your winForm) and does the communication between both. This observer gets notfied by the subject(s) in your native code when the collection size changes and then calls the method in your winForm.
Additional Information for the interaction native c++ <-> c++/CLI (see comments below):
Because it isn't a simple thing to store a .Net reference in native code I recommended the extra observer class to encapsulate the interaction.
In your case this means not to try to implement the winform directly as a observer class. With the additional native observer class between your subject class and the winForm you can easily register the observer and you have the problem storing a managed reference only in this class. You have 2 options:
Implement the singleton pattern for your winForm to get a reference to your living instance of the Form. References can be stored temporarily as asual with Type^. You could use this to get the reference in the notify-method.
Implement the native observer class and store the reference from the beginning by using gcroot. In this case you maybe have to do some casts.
In both cases you then call at the notify method a public method of the winForm which does with the collection whatever has to be done. Also the references to the .Net Framework have to be setup for the project including this observer class (should already be done when all classes lie in the same project as the winForm).

Related

Where is the place for dependencies resolving using IoC within WPF app?

I have read in "Dependency Injection in .NET" by Mark Seemann that there should be a single place (per each) where Register, Resolve and Release have to be called. Now, I'm trying to set up the environment of a new WPF project. Our team has decided to use Caliburn.Micro as MVVM-framework with MEF as IoC.
So, I clearly understand where Register has to be called, but what about Resolve?
I also have read in the book, that in ASP.NET MVC app there is a place where Resolve has to be called:
override IController GetControllerInstance(RequestContext requestContext,
Type controllerType) {
return (IController)this.container.Resolve(controllerType);
}
But where should the call reside within a WPF app? Besides, can Caliburn help somehow with accomplishing this issue?
But where should the call reside within a WPF app? Besides, can Caliburn help somehow with accomplishing this issue?
Actually Caliburn.Micro handles this part for you, because when you derive your bootstrapper from the existing BootstrapperBase or Bootstrapper<TRootModel>, those bootstrappers call a method called Start() that initiaties a sequence of activities which composes the entire object graph of your application starting with TRootModel or whatever you call DisplayRootViewFor(Type viewModelType) for.

ICommand vs IValueConverter

I am new to WPF. I am currently developing an application in WPF where I had to enable/disable a button based on a value from database. I found solutions on the net to do so using Command as well as Converters. So which one is a better solution and why?
When working with buttons it would be best to use the command implementation , since it is built in
and you can provide a command parameter for predicate , the converter is something you would need to
write , instance and place in each place you would wan't to use it .
To summarize a command with CanExecute would be more reusable and maintainable .
Since you're new to WPF, I truly recommend you start learning Rx Extensions and Reactive UI as well.
Reactive UI provides a Command Framework that can really help you in complex scenarios where your commands depend on many flags/conditions that can be computed through lambda functions and Observables.
If you want to create a complex Application you should definitely start learning MVVM. For a simple application use MVVM Light. For more complex WPF applications you can go for Reactive UI or Microsoft PRISM.
Have a look at Reactive UI here . There's a few Command examples in the Home page of Reactive UI but you can also get more samples in here
For instance you could declare an ICommand like this:
DisplayCommand = new ReactiveCommand(this.WhenAny(x => x.Name, x => !string.IsNullOrEmpty(x.Value)));
Have a look at the documentation.
As mentioned previously, you should use a Command instead of a converter for this scenario.
In addition, if the events you want to listen for are other ones besides click then use the System.Interactive behaviors/actions as described here.

Accessing User Application Settings in a WPF Prism 4 module

I have developed a Microsoft Prism 4.0 application and I am struggling to understand how to make the user application setting functionality available to modules.
e.g. a Properties.Settings.Default.MyProperty.
I can define a simple class that gets populated via the bootloader (which does have a handle to the properties) and inject that into the modules but If I want to save a change of property, I need believe I need a handle to the Properties.Settings context which is not available to my modules (which are simple class libraries).
Your scenario sounds like the perfect reason to use a "Service" class. Create an interface and class called IUserSettingsService and UserSettingsService that has the information (or can load and save it from where it is stored).
Read Chapter 3 of the Prism 4.0 help file, Managing Dependencies Between Components, Registering Types with (either Unity or MEF, depending on what you are using as your DI Container).
Then, in your ViewModel that needs the user settings, locate and use your service. In MEF, it is as simple as adding a property of type IUserSettingsService with an [Import] attribute, or using [ImportingConstructor] and having a parameter of type IUserSettingsService. With Unity, you access the service through the container. See Chapter 10 of the Prism help file - Advanced MVVM Scenarios.
Added after comment discussion:
Because you need your service to be in the context of your main application, you can implement your service class there. Create the interface for your service in a shared library that can be used by both the main project and your modules. Finally, load the service in the bootloader class instead of in a module.

How to use entitycollection for binding to wpf UI

I'm using EntityFramework for data access and wpf as UI. If I bind WPF components to navigation properties of my entity classes(usually EntityCollection<EntityClass>, exposed as IList<T> in service layer), UI is not updating the changes. I know i have to use ObservableCollection<T> or such, but I need some guidance on how to use it without iterating back and forth upon save and retrieval processes.
(As you guessed, I'm new to WPF; so target your answers for a WPF beginner)
You don't have to use ObservableCollection. WPF actually depends upon INotifyCollectionChanged, which ObservableCollection implements. So if you create a wrapper collection which implements this interface and forwards the operations onto the EntityCollection and raises the events, you should be good (as long as you modify the collection via the wrapper and not the underlying collection. A similar concept is used for read-only collections (wrap an existing collection and interact with wrapper), simple Decorator pattern.
You can't use it directly (and have the changes be reflected).
Here is a link that explains how someone else solved this problem
I faced the same problem in Silverlight LOB applications
I've created a silverlight library called ObservableCollections accompanied with visual studio 2012 addin and NUGet support, to generate the boilerplate code in order to wrap the EntityCollection with ObservableEntityCollection class, I know your question is about WPF but it could help.
http://observableec.codeplex.com/

How does the Winforms Designer instantiate my form?

I'm developing my own WinForms designer. It must be able to load existing custom form types. One of the issues I hit is forms without a default ctor: My code currently instantiates the form before it can load it into the designer, which requires a default ctor.
OTOH, VS2008 is able to load such forms. I believe it doesn't actually instantiate my form (as noted in this question): Even default ctors are not executed. And it doesn't truly execute InitializeComponent(). I just added a messagebox in that function and it doesn't show.
It looks like it dynamically mimic the custom form type and executes only parts of the code in InitializeComponent which it thinks is relevant.
Does anyone know where I can find more information regarding how the VS designer works.
TIA.
Note: I found this related question without satisfying answers
EDIT: Additional info: Steve points me to CodeDom, which is very insteresting. My problem though is that the types I need to load into my designer are already compiled instead of being available as source code. I can't find any way to apply CodeDom deserialization to compiled code.
Found this here:
When you open a new Windows
Application project in VS, you see an
empty form called Form1 in design
view. Now, you haven't built the
project yet, so how is the designer
able to create an instance of Form1
and show it? Well, the designer is not
really instantiating Form1 at all. It
is creating an instance of the base
class of Form1, i.e.,
System.Windows.Forms.Form. With a
basic knowledge of object oriented
programming, you will find that this
intuitively makes sense. When you are
designing Form1, you start with the
base class, Form, and customize it.
This is exactly what the designer
helps you to do.
Now let's say you added a bunch of
controls to the Form and closed the
designer. When you reopen the
designer, the controls are still
there. However, the base class Form
doesn't have these controls on it, so
if the designer isn't running the
constructor of Form1, how did it show
the controls? The designer does this
by deserializing the code in
InitializeComponent. Each language
that the designer supports has a
CodeDomProvider that is responsible
for providing a parser that parses the
code in InitializeComponent and
creates a CodeDom representation of
it. The designer then invokes a set of
CodeDomSerializers to deserialize this
into actual Controls (or more broadly,
Components) that it can add to the
design time Form. Now, I have glossed
over a lot of details in that
description, but the point here is
that Form1's constructor and
InitializeComponent are never really
invoked. Instead, the designer parses
the statements in InitializeComponent
to figure out what controls to
instantiate and add to the form.
The above is how Windows Forms designer in Visual Studio loads a form. If what you are looking for is a way to create an instance of a form that has no default constructor and still have access to the contained components/controls, I'm not aware of a solution. The only method I'm aware of that allows you to bypass the lack of a default constructor is FormatterServices.GetUninitializedObject, but beware ...
Because the new instance of the object
is initialized to zero and no
constructors are run, the object might
not represent a state that is regarded
as valid by that object.
I too have an app that requires instantiating compiled forms but have always used Activator.CreateInstance and required other developers to include, at the very least, a private default constructor if they want their form accessible in my app. Since we own the entire codebase and everyone is aware of the requirement, this isn't a problem and works out well for us.
As an addition to Steve's answer, if you add a new Windows Form to a project, but make it abstract, you can still open it in the designer. However, if you add another form, and have it derive from the first (abstract) form, you get an error when attempting to open the form in the designer.

Resources