Visual Studio: How to write Editor Extensions with WPF - wpf

Im trying to write a editor extension for Visual Studio. I have the downloaded VS SDK and created a new Visual Studio Package project. But the dummy control created for me is a Windows Forms control and not a WPF control. I'm trying to replace it with a WPF-control but not doing so well. Is this possible anyhow?
Another related question: Is it only possible to write text-editors? What I really want is a editor that looks more like a form with many different fields. But it doesn't seem to be what this is made for? There are a lot of interfaces on the EditorPane that imply a text-editor model only.
Ideally I want a editor much like the resx-editor where the file being edited has xml-content and the editor-ui is not a single textbox and where a generated cs-file is being outputted as a sub-file. Is this possible to do with editor extensions?

This is explained in detail here: WPF in Visual Studio 2010 – Part 4 : Direct Hosting of WPF content
So, if you use the standard Extensibility / Custom Editor sample that comes with the Visual Studio SDK, what you can do to test it is this:
1) Modify the provided EditorFactory.cs file like this:
// Create the Document (editor)
//EditorPane NewEditor = new EditorPane(editorPackage); // comment this line
WpfEditorPane NewEditor = new WpfEditorPane(); // add this line
2) create for example a WpfEditorPane.cs file like this:
[ComVisible(true)]
public class WpfEditorPane : WindowPane, IVsPersistDocData
{
private TextBox _text;
public WpfEditorPane()
: base(null)
{
_text = new TextBox(); // Note this is the standard WPF thingy, not the Winforms one
_text.Text = "hello world";
Content = _text; // use any FrameworkElement-based class here.
}
#region IVsPersistDocData Members
// NOTE: these need to be implemented properly! following is just a sample
public int Close()
{
return VSConstants.S_OK;
}
public int GetGuidEditorType(out Guid pClassID)
{
pClassID = Guid.Empty;
return VSConstants.S_OK;
}
public int IsDocDataDirty(out int pfDirty)
{
pfDirty = 0;
return VSConstants.S_OK;
}
public int IsDocDataReloadable(out int pfReloadable)
{
pfReloadable = 0;
return VSConstants.S_OK;
}
public int LoadDocData(string pszMkDocument)
{
return VSConstants.S_OK;
}
public int OnRegisterDocData(uint docCookie, IVsHierarchy pHierNew, uint itemidNew)
{
return VSConstants.S_OK;
}
public int ReloadDocData(uint grfFlags)
{
return VSConstants.S_OK;
}
public int RenameDocData(uint grfAttribs, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew)
{
return VSConstants.S_OK;
}
public int SaveDocData(VSSAVEFLAGS dwSave, out string pbstrMkDocumentNew, out int pfSaveCanceled)
{
pbstrMkDocumentNew = null;
pfSaveCanceled = 0;
return VSConstants.S_OK;
}
public int SetUntitledDocPath(string pszDocDataPath)
{
return VSConstants.S_OK;
}
#endregion
}
Of course, you will have to implement all the editor logic (add interfaces, etc.) to mimic what's done in the Winforms sample, as what I provide here is really the minimal stuff for pure demonstration purposes.
NOTE: this whole "Content" thing only works starting with Visual Studio 2010 (so you need to make sure your project references Visual Studio 2010 assemblies, which should be the case if you start a project from scratch using Visual Studio 2010). Hosting WPF editors within Visual Studio 2008 is possible using System.Windows.Forms.Integration.ElementHost.

I'm not sure if the above is possible but a quick search did turn up this:
http://karlshifflett.wordpress.com/2010/03/21/visual-studio-2010-xaml-editor-intellisense-presenter-extension/
and this:
http://blogs.msdn.com/b/visualstudio/archive/2009/12/09/building-and-publishing-an-extension-for-visual-studio-2010.aspx
Failing that, could you not host a WPF control inside the winforms control using ElementHost? I know its a lame workaround but might allow you to develop in your favourite toolkit while you find a more permanent solution.
Best regards,

There is a sample VS Extension Package application source code on MSDN: Designer View Over XML Editor.
Description from site:
This Sample demonstrates how to create an extension with a WPF-based Visual Designer for editing XML files with a specific schema (XSD) in coordination with the Visual Studio XML Editor.
Admittedly solution is dedicated for VS2010 Extension Package, however it can be simply converted and attuned to VS2012 format - Target platform should be change to .NET 4.5, thereafter some references to VS2012 assemblies (v.11.0) should be added to build and run startup project:
Microsoft.VisualStudio.Shell.11.0.dll
Microsoft.VisualStudio.Shell.Immutable.11.0.dll
Microsoft.VisualStudio.Shell.Interop.11.0
In case of problems, please visit Q & A section of the site.

Related

Creating classical Properties.Settings in .Net 6.0 (Core) "Class Library" projects

Created a new "WPF Application" .NET 6.0 project
There creating classical Application Settings was easy in project->properties->Settings->"Create or open application settings"
Observed: the project gets a new folder "Properties" which has a yellow Folder icon with an additional black wrench symbol, okay
It contains a new item Settings.settings that can get edited via classical Settings Designer looking like it used to look in .Net 4.8, and a new App.config XML file is getting created automatically in the project's root folder which also looks like it used to in .Net 4.8, okay
Now the same procedure can apparently only be done manually in
a new "Class Library" project being added in the same solution where I would want to use that Properties.Settings / app.config feature pack for storing a DB connection string configurably:
the new sub-project does not seem to have a "Settings" option in the project Properties dialog (as opposed to a .Net4.x would have had)
the new Properties folder and new Settings file can be created successfully there too manually as described in Equivalent to UserSettings / ApplicationSettings in WPF .NET 5, .NET 6 or .Net Core
but doing a "Rebuild solution" gives an
Error CS1069 The type name 'ApplicationSettingsBase' could not be found in the namespace 'System.Configuration'. This type has been forwarded to assembly 'System.Configuration.ConfigurationManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly. ClassLibrary1 C:\Users\Stefan\source\repos\WpfCorePropertiesSettings\ClassLibrary1\Properties\Settings.Designer.cs 16 Active
as a next step adding NuGet package "System.Configuration.Abstractions" to the Class Library project cures the symptom, "rebuild solution" makes the error disappear.
TLDNR, actual question: is that sequence an acceptable solution or a kludge to avoid?
To me the NuGet package description does not sound as if the package was made for that purpose, and I have not heard the maintainers' names before (which might or might not matter?)
https://github.com/davidwhitney/System.Configuration.Abstractions
TIA
PS:
Maybe I don't understand something...
Why create "Equivalent to UserSettings"?
My configuration is Win10+VS2022. I am creating a WPF .Net6 project. I go to the "Project Properties" menu. In the menu of the project properties tab (column on the left) there is an item Options. When selected, if the settings have not yet been created, there will be a small comment and a link to "Open or create application settings".
Unfortunately, I have Russian localization, so the screenshots are with Russian names.
Addition
But an additional "Class Library" sub-project does not seem to have that Project Properties option in my En/US localization. Does it in yours?
These are the APP settings.
Therefore, they do not make much sense in the library.
But if you need to, you can just copy the class to the library and then set up the links you need.
To do this, type in the application code the line Properties.Settings.Default.Save();. Move the cursor to Settings and press the F12 key.
You will be taken to the source code for the Settings class declaration. This code is generated by a code generator.
After moving to, copy all the source code into a class in another project. After the migration, you may need to add references in the project, fix the namespace and add usings.
As for the parameters in the «Class Library» project, it probably depends on what type this library is.
I have such settings in the «Class Library for WPF».
But in Libraries for Standard - no.
In the meantime I'm happy with a custom "AppSettings.json" approach.
After removing the previously described "classical app.config" approach, and after adding two NuGet packages:
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
... I created a custom Json file on "Class Library" (sub)project level in Visual Studio manually, and set its CopyToOutputDirectory property
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
And added an 'IConfigurationBuilder` part:
using Microsoft.Extensions.Configuration;
namespace Xyz.Data
{
internal class AppSettingsConfig
{
public AppSettingsConfig()
{
IConfigurationBuilder builder = new ConfigurationBuilder();
_ = builder.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "AppSettings.Movies3Data.json"));
var root = builder.Build();
AttachedDb = root.GetConnectionString("AttachedDb")!;
}
public string AttachedDb { get; init; }
}
}
And then made it a "Jon Skeet singleton"
/// <summary>
/// Singleton as described by Jon Skeet
/// </summary>
/// https://csharpindepth.com/Articles/Singleton
internal sealed class AppSettingsConfigSingleton
{
private static readonly Logger log = LogManager.GetCurrentClassLogger();
private AppSettingsConfigSingleton()
{
log.Trace($"{nameof(AppSettingsConfigSingleton)} ctor is running");
IConfigurationBuilder builder = new ConfigurationBuilder();
_ = builder.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "AppSettings.Movies3Data.json"));
var root = builder.Build();
AttachedDb = root.GetConnectionString("AttachedDb")!;
}
static AppSettingsConfigSingleton() { }
public string? AttachedDb { get; init; }
public static AppSettingsConfigSingleton Instance { get { return Nested.instance; } }
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly AppSettingsConfigSingleton instance = new();
}
}
And it "works well" by also reading JSON content just having been modified by admins at run-time. (Which would be the Entity Framework Core "localdb" location for the unit-of-work pattern in a multi-UI solution). Thanks again to you too, #EldHasp

IOleCommandTarget IDM_BLOCKFMT doesn't work when changing windows locale to non-english

I have the following c# .Net code in WPF app code:
public static void ClearList(IHTMLDocument document)
{
if (CanSetBlockFormat(document))
{
OleCommandTargetHelper.Execute(document, MsHtmcid.IDM_BLOCKFMT, new object[] { "Normal" });
}
}
where:
internal static object Execute(IHTMLDocument document, MsHtmcid command, object[] arguments)
{
var commandTarget = (DocObj.IOleCommandTarget)document;
var retVal = new object[] { null };
var hr = commandTarget.Exec(
ref NativeMethods.Guid_MSHTML,
(int)command,
(int)DocObj.OLECMDEXECOPT.DONTPROMPTUSER,
arguments,
retVal);
return retVal[0];
}
This is used for editing and formatting html text in WebView/WPF, where the web browser used is internet explorer and is used as a kind of rich text editor generating required HTML.
In this particular case it is used to remove formatting from bulleted or numbered list.
Can anyone tell me why this code doesn't work the moment I change windows langauge settings to non-english (Austrian for example?)
windows 10 language settings

How to create Visual Studio 2012 WPF custom designer/editor [duplicate]

Im trying to write a editor extension for Visual Studio. I have the downloaded VS SDK and created a new Visual Studio Package project. But the dummy control created for me is a Windows Forms control and not a WPF control. I'm trying to replace it with a WPF-control but not doing so well. Is this possible anyhow?
Another related question: Is it only possible to write text-editors? What I really want is a editor that looks more like a form with many different fields. But it doesn't seem to be what this is made for? There are a lot of interfaces on the EditorPane that imply a text-editor model only.
Ideally I want a editor much like the resx-editor where the file being edited has xml-content and the editor-ui is not a single textbox and where a generated cs-file is being outputted as a sub-file. Is this possible to do with editor extensions?
This is explained in detail here: WPF in Visual Studio 2010 – Part 4 : Direct Hosting of WPF content
So, if you use the standard Extensibility / Custom Editor sample that comes with the Visual Studio SDK, what you can do to test it is this:
1) Modify the provided EditorFactory.cs file like this:
// Create the Document (editor)
//EditorPane NewEditor = new EditorPane(editorPackage); // comment this line
WpfEditorPane NewEditor = new WpfEditorPane(); // add this line
2) create for example a WpfEditorPane.cs file like this:
[ComVisible(true)]
public class WpfEditorPane : WindowPane, IVsPersistDocData
{
private TextBox _text;
public WpfEditorPane()
: base(null)
{
_text = new TextBox(); // Note this is the standard WPF thingy, not the Winforms one
_text.Text = "hello world";
Content = _text; // use any FrameworkElement-based class here.
}
#region IVsPersistDocData Members
// NOTE: these need to be implemented properly! following is just a sample
public int Close()
{
return VSConstants.S_OK;
}
public int GetGuidEditorType(out Guid pClassID)
{
pClassID = Guid.Empty;
return VSConstants.S_OK;
}
public int IsDocDataDirty(out int pfDirty)
{
pfDirty = 0;
return VSConstants.S_OK;
}
public int IsDocDataReloadable(out int pfReloadable)
{
pfReloadable = 0;
return VSConstants.S_OK;
}
public int LoadDocData(string pszMkDocument)
{
return VSConstants.S_OK;
}
public int OnRegisterDocData(uint docCookie, IVsHierarchy pHierNew, uint itemidNew)
{
return VSConstants.S_OK;
}
public int ReloadDocData(uint grfFlags)
{
return VSConstants.S_OK;
}
public int RenameDocData(uint grfAttribs, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew)
{
return VSConstants.S_OK;
}
public int SaveDocData(VSSAVEFLAGS dwSave, out string pbstrMkDocumentNew, out int pfSaveCanceled)
{
pbstrMkDocumentNew = null;
pfSaveCanceled = 0;
return VSConstants.S_OK;
}
public int SetUntitledDocPath(string pszDocDataPath)
{
return VSConstants.S_OK;
}
#endregion
}
Of course, you will have to implement all the editor logic (add interfaces, etc.) to mimic what's done in the Winforms sample, as what I provide here is really the minimal stuff for pure demonstration purposes.
NOTE: this whole "Content" thing only works starting with Visual Studio 2010 (so you need to make sure your project references Visual Studio 2010 assemblies, which should be the case if you start a project from scratch using Visual Studio 2010). Hosting WPF editors within Visual Studio 2008 is possible using System.Windows.Forms.Integration.ElementHost.
I'm not sure if the above is possible but a quick search did turn up this:
http://karlshifflett.wordpress.com/2010/03/21/visual-studio-2010-xaml-editor-intellisense-presenter-extension/
and this:
http://blogs.msdn.com/b/visualstudio/archive/2009/12/09/building-and-publishing-an-extension-for-visual-studio-2010.aspx
Failing that, could you not host a WPF control inside the winforms control using ElementHost? I know its a lame workaround but might allow you to develop in your favourite toolkit while you find a more permanent solution.
Best regards,
There is a sample VS Extension Package application source code on MSDN: Designer View Over XML Editor.
Description from site:
This Sample demonstrates how to create an extension with a WPF-based Visual Designer for editing XML files with a specific schema (XSD) in coordination with the Visual Studio XML Editor.
Admittedly solution is dedicated for VS2010 Extension Package, however it can be simply converted and attuned to VS2012 format - Target platform should be change to .NET 4.5, thereafter some references to VS2012 assemblies (v.11.0) should be added to build and run startup project:
Microsoft.VisualStudio.Shell.11.0.dll
Microsoft.VisualStudio.Shell.Immutable.11.0.dll
Microsoft.VisualStudio.Shell.Interop.11.0
In case of problems, please visit Q & A section of the site.

What do I have to do so that a property will show at the datasource?

This is a windows forms question. forgive me if I explain what I do with too much detail but I asked with less detail before and it seems nobody read, because answers were completely off mark and I wasted bouty.
I have a Linq object called XX. It was created when I dropped my table on the .dbml file in visual studio.
Then, to make my interfaces easier to program I go to Data->Show Data Sources on visual Studio and create a object data source. All properties of the object appear at the data source.
But the linq class is partial, so i do:
partial class XX
{
private int _myValue;
public int myValue
{
get { return _myValue; }
set { _myValue = value; }
}
}
are you following so far ?
Then i go and recreate the object data source.
The property myValue does not show on the data source.
I tried decoratin it like this:
[Bindable(true)]
public int myValue
to no avail. This usualy does the trick for "non-linq" Plain classes.
So, the question is: What do I have to do so my property will show at the data source ?

Design time data in WPF

[using vs2010 & expression blend v4]
Hi - trying to load up some design time data in WPF and Blend, using Josh Smith's concept here: http://joshsmithonwpf.wordpress.com/2010/04/07/assembly-level-initialization-at-design-time/
e.g.
[AttributeUsage(AttributeTargets.Assembly)]
public class DesignTimeBootstrapperAttribute : Attribute
{
public DesignTimeBootstrapperAttribute(Type type)
{
var dep = new DependencyObject();
Debug.WriteLine("here..?");
if (DesignerProperties.GetIsInDesignMode(dep))
{
// TODO: Design-time initialization…
IBootstrapper instance = Activator.CreateInstance(type) as IBootstrapper;
if (instance != null)
{
instance.Run();
}
}
}
}
With my attribute here in AssemblyInfo.cs, where AppBootstrapper extends MefBootstrapper.
[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: DesignTimeBootstrapper(typeof(AppBootstrapper))]
I don't want to use the Blend sample data, a) as it doesn't seem to create data for ObservableCollection and b) I'm in design mode by definition, so things will change quite a lot, but my 'generated data' will not.
Anyway, nothing seems to be happening.
Q1: How is it possible to debug the design time initialisation of my bootstrapper?
Q2: Do I need additional blend namespaces/ attributes etc in my View XAML?
(In my bootstrapper I'm just registering a different module where I want to replace RunTimeService with a DesignTimeService, exporting the IService interface).
TIA
To debug this:
Open your project in VS2010
Set a breakpoint in the assembly attribute constructor
Start a new instance of Blend 4
From VS2010 use Debug -> Attach to Process: and choose Blend
Switch to Blend and open your project
Open a XAML file that references your sample data
Also, any Debug.WriteLine should appear in the VS2010 output window.
If you can't get the attribute method to work (I haven't tried it myself), you can use this method (which I have used) from MVVM Light:
private bool? _isInDesignMode;
public bool IsInDesignMode
{
get
{
if (!_isInDesignMode.HasValue)
{
var prop = DesignerProperties.IsInDesignModeProperty;
_isInDesignMode =
(bool)DependencyPropertyDescriptor
.FromProperty(prop, typeof(FrameworkElement))
.Metadata.DefaultValue;
}
return _isInDesignMode.Value;
}
}

Resources