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.
Related
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.
One small question. I know the toolbox in Visual Studio has all the necessary components, but I was wondering if we could introduce our own "custom-made" tools. For example, the listbox tool. I've created a "SpeechListBox" class in which I've mentioned all the methods that I want my listbox to use, but when I'm in the "SpeechListBoxApplication" class (where I wanna use this listbox), the listbox with my methods doesn't show up, instead the general listbox tool that doesn't have my methods shows up.
What I want is to write something like private speechListBox1 SpeechListBox; and somehow introduce a visual form to the design class without confusing it with the toolbox's listbox. Making the program realize that I want this type of list box with all the extended methods, not the general toolbox type.
Is there any way to either make our own listbox or add methods to the original listbox tool?
Well, if you derive your SpeechListBox from a class that either is or derives from System.Windows.Forms.Control, when you compile your project it will show up in the Visual Studio control toolbox.
If you aren't sure which class to derive from, you'll have to make some decisions. If you want to hand-draw everything yourself, derive straight from Control itself. If you want to build a control is is a composite of other controls, consider deriving from UserControl. You don't explicitly list exactly what you're trying to do with your SpeechListBox, but you may want to consider just using a ListBox but supplying it with custom drawn list items. You could do this by making your class derive from ListBox or just configuring a ListBox to do what you want right in the form on which the listbox resides.
Is your code in separate project? Then you have to add that project to your SpeechListBoxApplication project's references in the solution explorer.
Otherwise your inherited control (public class SpeechListBox : ListBox) should show up, when in the GUI Designer in the toolbox in either the Common section or a section labeled after the project.
I've been unable to make this work because of what I believe is a glitch in Visual Studio, so I'd really appreciate if someone could attempt this situation and share what happens.
I have setup in a solution 2 projects:
- a C++ application which has been CLI enabled (.exe)
- a C#/WPF class library which has a .xaml form inside with a matching .cs window class (.dll)
I want to spawn the WPF window inside my C++ application, so I import its reference and create a new instance of the window and run under a new application context. Thats works fine.
I now want to make classes out of this window and handle different events inherited from protected functions in the C# window, so In the C++ assembly make a public ref class whom child is the .cs class of the .xaml powered window. This compiles fine.
ie:
public ref class myCPPWindow : myWPFWindow { ... };
I then change the window I spawn to the parent class which is located in the C++ assembly rather than the base class located in the C# assembly. Now I get an error on the InitializeComponent() part of the base C# class while loading the .xaml window that I require saying that it fails to load the .xaml window source from the C# assembly even though the base class works. Can anyone give an explanation/fix for this?
It looks like a common [library;user control]-[application;derived control] issue in WPF - I reproduced that even without C++. Without digging into explanation, general workaround is either aggregating "base" class or re-degisning base class to be templated control instead of user control (e.g. without .xaml file). If I understand correctly, your question is the same as The component does not have a resource identified by the uri question.
I am trying to create a new Control (Let us for now forget about UserControl or CustomControl).
I open a Windows phone Application project in vs2010 and then add a new item Windows phone Control Library and then I use it in my phone application.
Everything works fine. Now if I want to create a windows phone control to be used in another application how should I be going about it? New application means a separate new solution.
Phone Application1 -> Have my own control inside the solution and hence I am able to use it.
How can I use this same control in another new solution?
I am not sure if this has been answered before. Does any solution already exist?
Cavet:
I tried creating a new Windows phone Class Library in a vs2010 instance but it didn't work because it didn't had a xaml form. When I tried to manually include it and write the logic it build successfully but now even if I include the dll of this project I don't get the control in the toolbox. This process does not make much sense to me as I am creating a class library and not a control but still wanted to give it a try.
To show controls from your assembly in the toolbox, you should do design-time assembly. You can look at these articles for the beginning:
Link2
Link1
It's not easy and perhaps you can live without that if your control assembly is not a commercial product. To use any control from other assembly in application:
add project reference to your control assembly
include xmlns namespace attribute corresponding to your assembly to any page of your application. Just start typing 'xmlns=' near other xmlns definitions in the page header and VS intellisense will show you the list of available namespaces. Choose the needed one and then set namespace alias to use on the page. It should look something like xmlns:myNamespace="clr-namespace:MyAssembly.Namespace.;assembly=MyAssembly"
insert control from your assembly into page using xaml editor
now you should be able to see your control in xaml designer and edit its properties from the property grid
.
I am not sure if the above mentioned method would solve the case, because as far as I have seen it is not possible to create a Windows Phone Control Library in VS2010. So this is what I did..
Created a Windows Phone Control Library and write my own custom control.
Build the project.
Back to Vs2010, added the reference to the control in the app in which I wish to use.
As simple as that. I don't know why it was initially a little bit confusing (perhaps I would have got confused with the binding and stuff). Anyways its quite simple though. Thank you for the reply.
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.