Add custom editor windows to Visual Studio window panes - c#
My Problem
I'm trying to build an extension to Visual Studio that allows code to be edited on a per-function basis, rather than a per-file basis. I'm basically attempting to display code in a similar fashion to Microsoft Debugger Canvas.
I'm wondering how to host multiple Visual Studio editors within a single window (I believe the windows are implementing IVsWindowFrame). The functionality I'm after can be seen below:
Each editor window retains typical functionality and interacts with third-party extensions as expected. (For example, VsVim functions correctly within these windows).
What I've Tried
I've spent almost two weeks researching and trying this stuff and I'm having a lot of trouble figuring out which services, interfaces and classes I'm going to be using.
Reading through MSDN
First off, most of the documentation discusses how to edit a single editor window and add adornments, tags, margins etc. It doesn't discuss the possibility of spawning multiple editors within a window pane.
I've looked through the documentation on a vast number of interfaces of interest to me including IVsTextBuffer, IVsTextView and IVsInvisibleEditor. Unfortunately I can't get some of these interfaces to play nicely together.
On top this, the usually excellent MSDN is extremely lacking in this area. Many of the interfaces contain only a list of members without even a basic remark on intended use and functional. (IComponentModel, for example).
Many of the interfaces make reference to a set of Editor Samples but the code cannot be read or downloaded on MSDN. Apparently it shipped with Visual Studio 2005, but I don't have this version of Visual Studio, nor can I find it.
Interacting with IVsUIShell
I can get access to all WindowFrames open using IVsUIShell.GetDocumentWindowEnum();
I see there is an IVsUiShell.CreateDocumentWindow() method, but I'm completely unfamiliar with the parameters it accepts, or if this is the correct path to go down.
What I need to do
Programatically create a dockable window pane
Programatically add editors to this window pane. (And ensure they're correctly registered within Visual Studio, the running document table, etc.)
Edit:
I'm sorry, I should have expanded on my steps. When I said I needed to register with the running document table and Visual Studio, it's because I want to actually edit the original document in my custom editor. Below is a short example of the functionality available in Debugger Canvas that I'm trying to recreate:
http://i.imgur.com/aYm8A5E.gif (I can't embed a .gif)
Alternatively:
If anyone knows where I can find the editor samples included with Visual Studio 2005 such as the Basic Editor Sample I'm sure I could figure this stuff out. The MSDN documentation has no code samples regarding these interfaces, which has made my job extremely difficult.
The Git Source Control Provider is an open source extension includes a tool pane that embeds a standard editor as a control within a custom WPF tool window. I would use this code as a reference for any Visual Studio 2010+ extension where I wanted to host an editor window in some custom location.
PendingChangesView.xaml includes a ContentControl named DiffEditor, the content of which will be the editor.
PendingChangesView.xaml.cs includes a method ShowFile, which calls a method to create the editor control and assigns the result as the content of DiffEditor.
ToolWindowWithEditor.cs includes a method SetDisplayedFile which returns a Tuple<Control, IVsTextView> interface, which provides access to a Control that can be added to a ContentControl as well as the IVsTextView for the text view. The heavy lifting is in this method.
Note that the SetDisplayedFile method includes several lines with the following form:
textViewHost.TextView.Options.SetOptionValue({name}, {value});
These lines perform key functionality for the Git Source Control Provider such as removing margins and making the window read only. There are many options available, so you'll want to review the documentation for DefaultTextViewOptions and DefaultTextViewHostOptions to apply the ones appropriate for your particular extension.
I haven't actually looked at the files that #280Z28 (why this username?) posted. I used to work on the Visual Studio editor and what you are trying to do has multiple facets to it that you should tackle independently:
Hosting multiple command targets inside a single IVsWindowFrame (this means that you'll have different elements inside the same pane from the point of view of Visual Studio's shell, and each of them need to have their own command handling. Consider the case where you put your caret in one of the mini-editors and want to undo using Ctrl+Z, moments later, you then place your caret into another mini-editor and do the same. Even though the WPF and Win32 focus have remained inside the same window frame (from the point of view of the Visual Studio Shell), the commands need to be routed to different components.
Using editor's that are displaying parts of another document. The mechanisms here that will be your friend are in the projection namespace. Projection essentially allows you to project a piece of buffer (or buffers) into a view. Ellision buffers are special case projection buffers that project from one source buffer into a target view while hiding areas of the buffer (this is most likely what you want). An example of a projection buffer is what happens inside a cshtml file. In that case, there is one buffer containing all the C# code, one buffer containing all the javascript, and one buffer containing the html and each compiler works off of that buffer, but the end user sees a projection of all these buffers into the editor's view with only relevant parts displayed (for example C# import statements are elided even though they exist in the real C# buffer.)
Managing the running document so that when an edit is made in a mini-editor, the real document is dirtied. You need to handle cases where the parent file is already open in the RDT in which case you want to dirty the same document when changes are made, and also cases where the document is not open, in which case you need to create a new entry in the RDT.
Also, please post to the Visual Studio forums, there are people who regularly check the forums and route the questions to corresponding devs.
Generally speaking, when it comes to the editor, avoid any traditional interfaces (anything that does not use MEF), so samples from Visual Studio 2005 should not be used as a reference point.
If you care enough and are in Seattle, you can try to go to campus as an MVP. There are days where you come to campus, and members of varying team will grab a laptop and come to your conference room and you can debug code together or hack away (while having access to debugging symbols and what not).
Last but not least, contact the code canvas guys, I'm sure they've solved many of the problems you are facing.
You need to register a tool window with your package extension; this can be done via the ProvideToolWindow attribute. The following article contains all the required information on how an editor can be hosted in a tool window: http://bit.ly/9VWxPR
Take a look at the WpfTextViewHost class; the article explains that this type is actually an UIElement, so I imagine that it´s possible to host multiple instances of it...
Related
AvalonDock: Auto-hide tool cannot be shown once hidden
I'm using Dirkster99/AvalonDock 4.70.0 I have an MVVM architecture that's very similar in structure to the VS2013 sample application. When I use a layout initialiser to make one of my tools auto-hide (just as the sample does), everything displays and functions correctly until I forcibly hide the tool (either by clicking on the X at top right, or by using the menu that is bound to the IsVisible property). Then, I find I can't make the tool visible again (by means of the menu). I cannot work out what I'm doing that is different from the sample, which works perfectly in this regard. If I disable the layout initializer and place the tool with others (so it does not auto-hide), it hides and shows correctly. If I float the tool before the hide, then it shows again correctly. Can anyone suggest how I can debug this? I've tried many times to trace the sample app alongside mine to work out how their behaviour differs, but the flow it quite complex and it's difficult to trace through event invocations. I've also tried to disable all the subtleties and complexities of the VS2013 sample in order to highlight the differences, but without success. More information: I can demonstrate the same behaviour with the 2013 sample application. It turns out that if you change the theme from its initial setting, then the hide/show sequence does not bring back the tool window. This applies whatever is chosen as the initial theme. I'll report this as a bug on GitHub.
How can i make an application with wpf that makes an new application in runtime?
I want to make an application WPF C# where i can make questions and drag drop picture and then save it. And then when i hit the save button it Makes an new application. Is this impossible? Does someone have an good url i can visit about this? I can't find anything when google it.
There already exists such an application - it's called Visual Studio. :-) Joking aside, to answer your question, yes, it is definitely possible to build such an application. There would be numerous ways of doing it, depending on specifics. One aspect of such an application, let's call it AppBuilder, would be to generate and compile code for the target application. It could be done, for example, using Roslyn, the C# compiler accessible from C#. Another aspect would be to allow the user to specify the questions, as you describe, and to allow the user to place images. Overall this would require something like a design surface with tools to manipulate the placement of the images and words, not unlike the WPF designer in Visual Studio. While the user builds the application, there has to be a way of them to save their work, to be able to come back to it later. Does every Save generate and compile the target application? Probably not. So there is a need for a persistence mechanism, and a database, or structured file of some sort, to save the user's work in a form that can later be read back and the project reconstituted in memory. Those are just the three most obvious features that such AppBuilder would need to support. Now for a reality check: it would not be simple, and depending on your specific requirements, it could get quite complicated. What about debugging the generated application? What about styling? Etc., etc. I don't mean to discourage you, but maybe you can provide more information about what exactly you want to accomplish, and then we could discuss more.
An adornment for the IDE itself
Trying to get started with VS2015 Extensibility. What I have in mind can be classified as an adornment. So I did some research and found sample templates and some MSDN pages that helped me create a basic adornment. Unfortunately though these pages always talk about text adornments that work inside the text editors only, whereas my adornment will work across the entire IDE, so at times visuals might appear on top of the Solution Explorer, or the Toolbox etc. There doesn't appear to be a built-in template for that. Can anyone point me in the correction direction about it?
Is it possible to modify the Navigation Bar in Visual Studio, or to otherwise add a similar graphical element to the code editor?
I like the grouping and browsability that regions provide in C# code but don't like the manual process of maintaining them (even auto-formatting tools are not perfect as they take awhile for large files), and other developers don't like them at all, so a better solution would be one that is done automatically by the IDE and without touching code. Visual Studio already has something along these lines with the Navigation Bar to browse classes and members alphabetically, but it provides no grouping by code element type. What I'd like to do is have the Navigation Bar have three sections instead of two: the first shows classes, the second shows members sorted alphabetically, and the third would show members nested by element type, like regions provide (e.g. Fields, Properties, Public Methods, Event Handlers, etc.). Can I gain access to this Navigation Bar in any way through the Visual Studio SDK, and if not, could I add a similar graphical element to the code editor and build it from scratch? The alternative is implementing my idea in a tool window and docking it, similar to ReSharper's File Structure window, which would be less ideal. Thanks!
I don't think you can extend built-in navigation bar for what you want, but in Visual Studio 2010 you can create your own nav bar as a view margin IWpfTextViewMargin. In your implementation you would need to scan current file for classes and members using the Code Model API and synchronize what you show with the caret movement.
Why does C# designer-generated code (like Form1.designer.cs) play havoc with Subversion?
My workshop has recently switched to Subversion from SourceSafe, freeing us from automatic locks. This led to concurrent editing of the Forms, which is wonderful. But when multiple developers commit their changes, the code files created by the designer (all the files named TheFormName.designer.cs) cause conflicts which are very difficult to resolve. As far as I can tell, this is because the code generated by the designer is heavily re-arranged whenever the user modifies it, no matter how little the actual change really did. How do I make these conflicts easier to resolve? Is there some way to tell the designer to modify the code less? How do you, the experienced C# teams, deal with concurrent modification of a Form?
Here are some things to try: Make things more modular. Use components like User Controls etc. to split forms into multiple, smaller physical files. Use presentation layer design patterns like MVP to move code out of views and into standard POCO classes. Recent versions of SVN allow you to take hard locks - use this to avoid complex merge scenarios. Hope that helps.
I'm pretty sure there is no silver bullet for this problem as the designer stomps all over the designer.cs. All I can suggest is to minimise the use of the designer. Personally I only hook to events in code and only use the designer only for initialisation and positioning. As such it isn't too hard to fathom differences in a changeset ("oh, someone has added a button", "oh, someone has changed how it looks slightly").
Yep, Designer's random rearranging sure is irritating. Does Microsoft use their own tools? Does Microsoft look at what they check into version-control? It boggles the mind. Our team's "solution" is to hand-edit the Designer files after we're done editing them, to put things back to where they were, so that the text-based diff is readable, and so concurrent changes can be merged sanely. Luckily, most of Visual Studio's rearranging is simple-minded, so this works. Sadly, we've found that this step is necessary to verify correctness -- we've found cases where Designer silently removes things that are needed, leading to broken code. So this step has to be done in order to work around whatever data-destroying bugs lurk inside. Sigh. Since Microsoft has a poor track record of fixing its bugs, the only solution may be to improve Mono's WinForms Designer so that it's ready for prime time.
I'm not familiar with C# or the Windows Form Designer, but looking at some designer.cs files I could find online they don't have a particularly complicated structure. What parts of it are being re-arranged? I guess it's mostly the order of the properties in the InitializeComponent() method that's jumbled up? If that's the case, you might be able to write a simple script that re-orders those lines alphabetically, say (especially if you never edit these files manually anyway), and use that as a pre-commit hook script in Subversion. Um, right... scratch that. The big red box at the bottom of that section says you're not supposed to modify transactions in hook scripts. But you might be able to find another way to run that script somewhere between the designer.cs file being changed and it being committed. Edit: Actually, given scraimer's comment on this: Total hack, but in the worst case, just before a merge, I could sort BOTH files, and make the merge simply a line-by-line affair... Can't you let Subversion set an external merge program? I've been using KDiff3, which can run a preprocessor command before doing diffs or merges, so you could automate that process.
It's true that the designer sometimes messes up the order of the controls in the code, which causes the file to look very different compared to a previous version. This indeed is a problem if the file is under version control. However, I found that the designer works quite reliably even in very large forms and user-controls if you follow some rules, and in those rare case where it does not, I have a easy way to force the designer into arranging the controls in the "correct" order again. My rules: The comment at the top of InitializeComponent() in every .designer.cs says: do not modify the contents of this method with the code editor. Well, if you know what you're doing, then it's absolutely no problem to edit this file manually, because this is what you need to do. Just make sure you have a backup. Typically, when you create a form or UC, you add some controls here and there and move them around until you find a nice arrangement. But in the .designer.cs file, the controls are ordered by the order of their creation, and not by your logic how they belong together. After finishing the creation of the form or UC, I reorder both the declarations (at the bottom of the file) and instantiations of the controls and their adding to the respective parent control (both in InitializeComponent()) until they are in the order that I want them to have. This makes it much easier to find them if you have to change a property of a control in the code. And it also makes it easier for version control, because you may easily see what part of your form or UC was changed just by seeing the place (rather towards top or bottom of the file?) of the change in a file comparison view. But changing the order in these 2 sections does not automatically change the order of all the parametrization code that comes after the instantiation part in InitializeComponent(). This will be done when you execute the solution to the OP's problem, which is described next. If you work with rule #2, then you need to do the same finishing work that you need to do when you encounter the problem that the OP describes: You have to force the designer to arrange controls in the order that they have in the declaration and instantiation. This can be done in a quite simple way (which worked for me in 99% of the cases so far): Save all files of the form or UC open the designer view move one of the controls (e.g. by selecting it and hitting 1x left arrow key) optional: look at the .designer.cs file and/or save the form or UC move the control back to have your intended design (e.g. by hitting 1x right arrow key) save the form or UC The designer will rewrite the whole .designer.cs file and your controls should now be in the "correct" order. There are rare cases where this does not help. These include DataGridViewRows in embedded DataGridViews and embedded UserControls. In these cases I additionally do similar finishing work which includes adding and removing a button: Save all files of the form or UC open the designer view add a button anywhere in the form or UC optional: look at the .designer.cs file and/or save the form or UC remove this button again save the form or UC
The only way I know of to truely avoid this problem when using a merge style source control system such as subversion is to hand code the forms and not use the designer. Obviously, this would not be good because hand coding these forms can take a while. The reason this happens is because the control properties are serialized by the designer in the order they are dropped on the form. Cutting and pasting can effect this order as well as moving a control so that it has a new parent (such as moving a control on to a panel when it was previously directly on the form). I had this problem on a large project and had to imploy a rather ugly approach - diff the designer.cs files against the check-in target revision and manually merge them using a merge tool. This isn't ideal, but it is the only way I see this working consistently with svn or another merge style source control tool. The other option would be to use a lock approach with source control, as others have pointed out, but this comes with unpleasant side effects as well.