Got a winform in project A (Main project) and which hosts a wpf user control and is maintained under different project called B
On click of a button on user control ,I wanted to query server which is in project "C" and retrieve data and show it on hosted wpf user control. I know its a bad coding practice to put a reference to s project "C" in project B which includes only custom controls .Any alternative thots would be appreciated...
To minimize project dependencies, create an interface in your control project (B) that reflects the operations your control requires.
Implement a class in your client (A) project that implements this interface (which will obtain the information you need from your data project (C) and pass it back through the interface method).
Pass the service class (implementing the interface) constructed in A to your control B when you initialize the control.
You make another project that is just a class library that can be shared across all three projects. You'll put the interfaces and/or the class implementations that need to be shared between the projects in the class library and then just use those in the server and the user-control projects.
Related
In my project I have implemented this plugin manager:
https://code.msdn.microsoft.com/windowsdesktop/Creating-a-simple-plugin-b6174b62
In this way I can add .DLL file and make my project more modular.
I wanna know if in one of these .DLL plugin I can add a .xaml with user interface, and use it inside my main project to visualize the content of that xaml in my main GUI.
In this way I can make my app more modular not only by code library but also with user interface.
Thanks
If you create a project that contains WPF UserControl items, then as long as you expose those items through the DLL interface then you can utilise them in another project.
You should be able to verify this very easily by doing something like the following:
1) Within your 'DLL' project make a public class SquareControl, which is simply a UserControl under the hood, and specifically a canvas containing a red square of a fixed size.
2) Within your utilising project, reference the DLL.
3) Within your utilising project, in C# code somewhere create an instance of SquareControl, and check in the debugger that its properties are as you expect.
4) Then create a UserControl within your utilising project, and open VS Designer for that control. Within the empty Grid that has been created for you drop an instance of SquareControl, and you should be able to see this within Designer. Getting your xaml namespace definitions can be awkward the first time around but there's plenty of help available for that. Then fire up the application and see it there.
I have a simple database application where an user can add or delete persons. Moreover, the application has a button "Add new button to application". This application is built using Prism framework. There are two modules:
RibbonControlModule (contains three buttons - Add Person, Delete Person, Add new button to application)
PersonModule (contains logic of adding and deleting persons)
My requirement is to add new buttons at runtime.
Let's imagine a situation. I live in Washington and I am happy with these two buttons(Add Person and Delete Person). But my friend, Bob, who lives in New Jersey would like to add new button Edit Button without recompilation the whole application. That is, Bob writes dll where he can edit person and then clicks Add new button to application in RibbonControlModule. After that, EditPerson button is appeared in RibbonControl and, for example, in ContextMenu. Maybe EditPerson dll would be another Prism module, I do not know.
That is, my requirements are:
pluggable controls
is it possible to plug control without recompliation? (like add-ons or extensions(Classic Notes for Opera) in Browsers(no need to restart a browser to use add-ons))
other programmers can develop their add-ons without using my source code
after once an user plugged a control, then this new control should be always plugged in the application.
Is it possible using WPF, MVVM and Prism? I really like Prism and do not want to deny Prism, but if "the end justifies the means", I would like to use other technologies.
If it is possible, then how can I do it?
This is what the MEF plugin architecture was designed for.
In short, you create an SDK containing an interface for your plugins and provide that to your clients as a standalone library. Your client's plugins then implement this interface and export them with the MEF Export attribute, which your main application then imports.
Where it gets a little tricky is with data templating, which is often a key component of MVVM. To cut a long story short your plugins need to put their data templates in a resource dictionary, give that dictionary it's own partial class file and export it with MEF's [Export] attribute. Your main app then needs to import these and add them to the global ResourceDictionary's 'MergedDictionaries' array. This is generally done separate to all your view model classes which are imported in a separate pass. The net effect is that your plugins can provides both views and view models at runtime, plus the data templates that bind the two together, and it will all work as though they'd been statically compiled into your original application. It also means you can create a plugin API for your customers without exposing the internals of your main application.
This is a very involved topic, and given how general this question is I'll be surprised if this question isn't flagged. If you'd like more details then let me know and we can move it to a discussion page.
You can do what you are describing using Regions in Prism. You can add a named region to your Ribbon that allows Prism modules to plug in new buttons into that region when the module first loads or later when a user clicks a button in some UI of your module as you describe.
To do that, add an ItemsControl into some pane within your Ribbon where you want the plugged in controls to show up. Add the prism namespace as a XAML namespace like so:
xmlns:prism="http://prismlibrary/"
Then add the following attached property to your ItemsControl:
prism:RegionManager.RegionName="CustomModuleCommandRegion"
Then in your module, inject IRegionManager either in the Module class itself if the commands should be added as soon as the module is loaded, or elsewhere in a ViewModel if it won't happen until a particular view is loaded or some user interaction like you described:
public ConstructorForModuleOrViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
}
private SomeCommandHandler()
{
var commandButton = // create button and wire up command here)
_regionManager.AddViewToRegion(commandButton, "CustomModuleCommandRegion");
}
You also have the option of using the RegisterViewWithRegion method of the region manager to set up a factory method or just specify the type of the view (i.e. button) that you want to inject. But for a button you will need to wire up a command handler before (or after) placing it into the region, so the AddViewToRegion is probably more appropriate. If it is something that is context sensitive - i.e. you only want the button to show up in the ribbon perhaps when a selection is made in a view - then you can get the region from the region manager first, and then use the Add and Remove methods on IRegion to add and remove your view (button) dynamically like so:
IRegion region = _regionManager.Regions["CustomModuleCommandRegion"];
region.Add(myCommandView);
...
region.Remove(myCommandView);
Using the combination of Prism Modules and Regions you can achieve runtime extensibility of your app - i.e. this new functionality could be "dropped in" without needing to recompile the main app or other modules in the app. To do that you need to use either configuration to specify your modules so that can be edited in the deployed environment to add a module, or you can use the DirectoryModuleCatalog to scan a directory for modules on start up. Its even possible to use a FileSystemWatcher to watch a directory for modules that are dropped in while the app is running and have them light up immediately when placed in the watched directory.
I found this post and I would like to do the second option in the first answer
2) If the app is only useful within the context of the parent apps,
say by being given objects or other arguments from the other apps,
consider refactoring the small app to allow the form's project to be
referenced by the parent apps. Then, your parent apps can simply
create a new instance of the form and display it:
var childForm = new SmallAppForm();
childForm.Owner = this; //the child window will close when its owner does.
childForm.Show();
I have some questions about what steps I would have to do in order to accomplish it.
The app that I trying to call can be found here.
To change it so that I have a main (parent) form that creates and calls this application like a class, would I add a new project that would be the "parent", add the Main to my new parent form so that it is the application. Then have a menu choice to start the wizard in the parent form in order to create and call my wizard like this?
CreateUserContext context = new CreateUserContext();
CreateUserWizard wizard = new CreateUserWizard(context);
Thanks for any guidance,
Leslie
Add a class library and put the classes of your SmallFormApp in it. This class library will be under the same solution. Then go ahead and reference this in your ParentForm and use the functions in it.
What I would do is to tranform the small aplication into a Class Library instead of a Winforms application. (It can also be a project within the solution, referenced by the main project)
Then, the parent application just references the small application and calls the new SmallAppForm()
Of course the SmallAppForm must be public.
Class Library is the project type. When you create a project, it can be console application, windows form application, class library and many others. So you should create a new project as class library type.
Copy all your forms of the small applications to this project, make the classes public.
(There's no program class in a class library, just the forms and other classes you created)
I wonder how to best develop a plugin framework where you can develop plugins with both C++/MFC and C#.
The Host Program is an existing program developed in native C++/MFC. To extend the functionality of this program, we have so far developed separate programs in C++/MFC and C# that run as separate applications or windows services. These programs are now communicating with the host application via files. This is obviously a rather clumsy method, and we therefore wish to bring them under a common plug-in framework.
Each program also has a separate management of settings. We therefore want each plugin to expand the settings window in the host application so that all settings can be managed in one place. How can we do that in a flexible and easy way?
(...) we therefore wish to bring them under a common plug-in framework. (...)
You can do that by creating a set of COM interfaces in a type library that you can wrap in a C++/MFC dll project. Then from either C++ or C# you can import this type library and create new COM classes that implement the predefined interfaces. Two disadvantages of these approach are: 1- That your main application will need to know the class IDs somehow to create instances of the COM classes. 2- Your plugins will need to be registered on the system or you will need to provide manifest files.
(...) We therefore want each plugin to expand the settings window in the
host application so that all settings can be managed in one place. (...)
This one is a bit more tricky, but you could try having a tab control with one tab for each plug-in, then pass the window handle of the corresponding tab to each plug-in during initialization, and then use that to place an ActiveX control on it. Creating ActiveX controls in MFC is well documented, and there is a sample project here for doing the same in C#: CSActiveX Sample
I've only just started using C#/VS this past week and wondered how to do something which, I think, should be quite simple:
What I want to do is extend the class used by a UI component and therefore implement my own methods in it - just for one instance of a UI component though. If I was using xcode/objective c I would normally just change the class name of the component in interface builder and it would become an instance of that class which would in turn extend the original UI class.
How do I do something comparable using C#/Visual Studio?
You can take any component class in Windows Forms and subclass it. Visual controls all derive from the Control class and you can do so as well.
If your component is a User Control (i.e., it derives from System.Windows.Forms.UserControl), it should automatically appear in the Toolbox after you build the project. For other components, you can add them to the Toolbox by right-clicking on the Toolbox and select Customize Toolbox, selecting the .NET Framework Components tab, clicking the Browse button, and selecting the DLL with the control.
Remember that all (or most) UI components are classes, so they can be "extended" just like any other class.
Some will have virtual members you can override to take special actions. In all cases, you can add properties, methods, and events to the components.
Once you've created and built them, you can use them from the Toolbox, just as though they were the "built-in" .NET components.