Silverlight C# - ComponentOne Spellchecker not loading dictionary - c#

This may be a long shot, but I'm using ComponentOne's Spellchecker control for Silverlight. I made a test project, added a plain textbox and a button to it, added the references to the C1.Silverlight and C1.Silverlight.SpellChecker bits, and added the dictionary file to my project.
In the code, I called up the spellchecker on button1's click event and it worked SPLENDIDLY. The spellchecker dialog shows up, and works exactly as it should.
Since that test was successful, I then tried to implement this into my existing project. I've had no success for absolutely NO reason that I can determine, since I used the EXACT SAME code.
Here's the code I use to call the component:
using C1.Silverlight;
using C1.Silverlight.SpellChecker;
using C1.Silverlight.Resources;
public partial class MainPage : UserControl
{
C1SpellChecker spellChecker = new C1SpellChecker();
public MainPage()
{
InitializeComponent();
spellChecker.MainDictionary.LoadAsync("C1Spell_en-US.dct");
}
private void btnSpelling_Click(object sender, RoutedEventArgs e)
{
var dlg = new C1SpellDialog();
spellChecker.CheckControlAsync(txtArticle, false, dlg);
}
The references to C1.Silverlight and C1.Silverlight.Spellchecker are added to this project as well, and the dictionary as been added in the same fashion as well. The issue seems to be that for whatever reason the dictionary is not loading, because the spellChecker.Enabled method returns whether or not the main dictionary has been loaded. If I call MessageBox.Show("SpellChecker Enabled = " + spellChecker.Enabled.ToString()); it shows false, even though the call to load the dictionary is there (as you can see).
What would cause the dictionary to not load? Have I added it to my project incorrectly somehow?
EDIT: I suspect that I have added the dictionary to the project incorrectly, because the ComponentOne reference states:
If C1SpellChecker cannot find the
spelling dictionary, it will not throw
any exceptions. The Enabled property
will be set to false and the component
will not be able to spell-check any
text.
I just don't know what's wrong though because it was added in the same way that it was in the test project (Right clicked on the project.web->Add->Existing Item)
As always, thank you!
-Sootah

You could add the dictionary to the Silverlight app as an embedded resource and then load it using this code:
public MainPage()
{
InitializeComponent();
// load C1SpellChecker dictionary from embedded resource
var asm = this.GetType().Assembly;
foreach (var res in asm.GetManifestResourceNames())
{
if (res.EndsWith(".dct"))
{
using (var s = asm.GetManifestResourceStream(res))
{
sc.MainDictionary.Load(s);
break;
}
}
}
}

I think this post is duplicated in our forum as well, but will answer first here. Please try this:
1) Try to access the .dct file using your browser. If you cannot see it, it's probably because your web server is not serving that type of files. You need ton configure the web server to allow it.
2) verify the URL you are using is correct.http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/86955/241328.aspx#241328
3) Check you are setting everything correctly: http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/81924/227790.aspx#227790
Hope this helps!

Related

Editor Pane in IWpfTextView is not Editable

I am trying to create a Visual Studio extension that will open a document window containing a custom control of mine that hosts an editor pane. I can get the document to load, the correct content type loads with my custom content extensions (classifier, quick info), a window with my custom control showing the editor pane loads, but the text cannot be modified. I can select and highlight text, but no keys work, no commands, and no mouse input other than text selection.
The following is what I have in my Package class:
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[ProvideEditorExtension(typeof(MyCustomEditorFactory), ".cust")]
[Guid(MyCustomExtensionsPackage.PackageGuidString)]
public sealed class MyCustomExtensionsPackage : AsyncPackage
{
public const string PackageGuidString = "ec2c4646-d0cc-42c6-b0a6-d0ff3e318cef";
#region Package Members
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
RegisterEditorFactory(new MyCustomEditorFactory(this));
}
#endregion
}
I have verified that the RegisterEditorFactory method is called, and that my editor factory is called when files with the .cust extension are opened.
The following is my editor factory:
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
using System;
using System.ComponentModel.Composition;
using System.Runtime.InteropServices;
[ComVisible(true)]
[Guid(EditorFactoryGuidString)]
public sealed class MyCustomEditorFactory : IVsEditorFactory
{
public const string EditorFactoryGuidString = "38AD95BA-8891-46A2-A5EA-25F5F36EEAE0";
private MyCustomExtensionsPackage _package;
private Microsoft.VisualStudio.OLE.Interop.IServiceProvider _vsServiceProvider;
[Import]
public IContentTypeRegistryService ContentTypeRegistry { get; set; }
[Import]
public ITextEditorFactoryService TextEditorFactory { get; set; }
public MyCustomEditorFactory(MyCustomExtensionsPackage package)
{
_package = package;
}
public int SetSite(Microsoft.VisualStudio.OLE.Interop.IServiceProvider psp)
{
_vsServiceProvider = psp;
return (VSConstants.S_OK);
}
public int Close()
{
return (VSConstants.S_OK);
}
public int MapLogicalView(ref Guid rguidLogicalView, out string pbstrPhysicalView)
{
pbstrPhysicalView = null;
return (VSConstants.LOGVIEWID_Primary == rguidLogicalView ? VSConstants.S_OK : VSConstants.E_NOTIMPL);
}
public int CreateEditorInstance(uint grfCreateDoc, string pszMkDocument, string pszPhysicalView, IVsHierarchy pvHier, uint itemid, IntPtr punkDocDataExisting, out IntPtr ppunkDocView, out IntPtr ppunkDocData, out string pbstrEditorCaption, out Guid pguidCmdUI, out int pgrfCDW)
{
ThreadHelper.ThrowIfNotOnUIThread();
ppunkDocView = IntPtr.Zero;
ppunkDocData = IntPtr.Zero;
pbstrEditorCaption = string.Empty;
pguidCmdUI = VSConstants.GUID_TextEditorFactory;
pgrfCDW = 0;
int retVal = VSConstants.E_FAIL;
if ((grfCreateDoc & (VSConstants.CEF_OPENFILE | VSConstants.CEF_SILENT)) != 0)
{
IVsTextLines textBuffer = null;
if (punkDocDataExisting == IntPtr.Zero)
{
IComponentModel mef = _package.GetService<SComponentModel, IComponentModel>();
mef.DefaultCompositionService.SatisfyImportsOnce(this);
IVsEditorAdaptersFactoryService eafs = mef.GetService<IVsEditorAdaptersFactoryService>();
textBuffer = eafs.CreateVsTextBufferAdapter(_vsServiceProvider, ContentTypeRegistry.GetContentType("CUST")) as IVsTextLines;
string fileText = System.IO.File.ReadAllText(pszMkDocument);
textBuffer.InitializeContent(fileText, fileText.Length);
string[] roles = new string[]
{
PredefinedTextViewRoles.Analyzable,
PredefinedTextViewRoles.Editable,
PredefinedTextViewRoles.Interactive,
PredefinedTextViewRoles.Document,
PredefinedTextViewRoles.PrimaryDocument
};
IWpfTextView dataView = TextEditorFactory.CreateTextView(eafs.GetDataBuffer(textBuffer), TextEditorFactory.CreateTextViewRoleSet(roles));
dataView.Options.SetOptionValue(DefaultTextViewHostOptions.LineNumberMarginName, true);
dataView.Options.SetOptionValue(DefaultTextViewHostOptions.ShowCaretPositionOptionName, true);
dataView.Options.SetOptionValue(DefaultTextViewHostOptions.ChangeTrackingName, true);
dataView.Options.SetOptionValue(DefaultTextViewOptions.ViewProhibitUserInputName, false);
IWpfTextViewHost wpfHost = TextEditorFactory.CreateTextViewHost(dataView, false);
MyCustomEditor editor = new MyCustomEditor(wpfHost);
ppunkDocData = Marshal.GetIUnknownForObject(textBuffer);
ppunkDocView = Marshal.GetIUnknownForObject(editor);
retVal = VSConstants.S_OK;
}
else
{
//code for document already open
}
else
{
retVal = VSConstants.E_INVALIDARG;
}
}
return (retVal);
}
}
There's a lot to unpack there, but ultimately I'm just
Creating an IVsTextBuffer from an IVsEditorAdaptersFactoryService
Loading the contents of the text buffer
Creating an IWpfTextView with the IVsTextBuffer from a ITextEditorFactoryService
Creating an IWpfTextViewHost with the IWpfTextView from the same ITextEditorFactoryService
Creating my my custom window pane and passing in the IWpfTextViewHost
Returning the IVsTextBuffer as the document data and my custom window pane as the document view
My custom window pane code is simply:
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text.Editor;
using System.Runtime.InteropServices;
[ComVisible(true)]
public sealed class MyCustomEditor : WindowPane
{
private IWpfTextViewHost _wpfHost;
public MyCustomEditor(IWpfTextViewHost wpfHost)
{
_wpfHost = wpfHost;
Content = new MyCustomEditorControl(wpfHost.HostControl);
}
}
I've omitted the code for the MyCustomEditorControl for the sake of brevity, but just assume it's a simple WPF UserControl with a ContentPresenter. The constructor just sets Content property of the ContentPresenter with the wpfHost.HostControl that's passed in.
All of this works insofar as displaying the contents of a file, but I just can't edit anything. It's like the input bindings aren't wired up or enabled, but I can't find what properties to set or enable on which objects, and the documentation is rather poor on this topic. I've gone through the Visual Studio extensions walkthroughs on MSDN, but it seems to be a mish-mash of pre-WPF and post-WPF APIs with no clear guidance on what the authoritative approach is.
Admittedly, I may be naive in assuming that the IWpfTextView would automatically handle user input, but in my defense it's created from an ITextEditorFactoryService and having "TextEditor" in the name carries certain implications.
I'm going to go through a rather exhaustive list of things I've tried and checked to hopefully help narrow down the possibilities or where my mistake is:
After the document window is open, I've checked the Running Document Table and there is an entry for it that is automatically created after CreateEditorInstance exits. It links to the data buffer that's returned, the correct file path, and has an edit lock but no read lock. I've inspected the RDT when C# files are opened in a normal editor window and those have read and write locks. I tried manually setting a read lock on the RDT as well, the counter increments, but that doesn't seem to make a difference.
I've inspected the return result from ITextBuffer.CheckEditAccess on the data buffer and it returns true so the text buffer is reporting it's editable.
The textview roles DO have an effect on the final rendered IWpfTextViewHost. If I add or omit roles, the appearance and functionality changes. For example, adding or removing "ZOOMABLE" adds or removes the dropdown box with the control zoom level. However, "EDITABLE" has no effect on editability.
The editor options DO have an effect. For example, adding or removing the line number margin options does show/hide the line numbers. However, ViewProhibitUserInputName has no effect on editability.
I don't create a code window with CreateVsCodeWindowAdapter because the resulting IWpfTextViewHost that can be retrieved from GetWpfTextViewHost is already parented to another control. If I disconnect it with (IWpfTextViewHost.HostControl.Parent as Border).Child = null, then the contents of IWpfTextViewHost.HostControl gets disposed of for some reason. The IWpfTextViewHost.HostControl loads and it displays a window with margins and scrollbars, but the content is blank and if I click into the left margin of the content pane then Visual Studio throws an ObjectDisposedException. Please note I'm not nulling out the host control itself or its contents, I'm only telling its existing parent it no longer has a child.
I've inspected the editor GUID property of the IVsWindowFrame that opens my document and it's set to the value returned in the pguidCmdUI parameter, which I believe is correct.
I'm not certain if the value being set for the pguidCmdUI parameter in the editor factory CreateEditorInstance is correct. I'm aware it's used for command routing, which might explain why I can't type or use the mouse, but I'm not sure what the correct value should be. I read somewhere it's supposed to be the GUID of the factory that created the editor, so I set it to the text editor factory GUID since that's what created the IWpfTextView. I tried setting it to my editor factory GUID at the top of the file, as well as typeof(IWpfTextView).GUID, Guid.Empty, and assorted other GUIDs, but there's no change.
If I pass my IWpfTextView into IVsEditorAdapterFactoryService.GetViewAdapter, I get back null.
If I create a IVsTextView from IVsEditorAdapterFactoryService.CreateVsTextViewAdapter, I can have both an IVsTextView and an IWpfTextView, but the two don't know about each other and I don't know see any way to map them. I don't even know if they need to be mapped, or if IVsTextView needs to exist or is just the legacy text view interface.
When I inspect the created IVsTextView, it's base type is a SimpleTextViewWindow that is an undocumented class that's internal to Microsoft's Visual Studio implementation, it has WpfTextView and WpfTextViewHost properties, but they're both null (or throw an exception that they can't be read) and are unsettable. Microsoft obviously has some internal voodoo magic to map IVsTextViews to WpfTextViews in their own code, but I don't know what it is.
I'm aware of other code samples that create an IVsInvisibleEditor and get the data buffer from that, but that seems kind of hacky. I mean, it technically works and no one seems to know of any alternative because the documentation in this area is so poor, so I'm not judging or criticizing, it just seems like that shouldn't be necessary. It's my (possibly incorrect) understanding that an invisible editor is a virtual editor that is created for documents that are opened in memory but not hosted in a window, but I'm hosting mine in a window. Additionally all of the working code samples I could find are all copy/pasting from the same Microsoft VSIX code example. In that example, the virtual editor is created in a tool window that's created under the assumption that a document is already open in an existing editor window. So that tool window is creating a virtual editor side-by-side to a physical one for a tool window. If I follow the same invisible editor approach, then I'm effectively creating a virtual editor in memory and then a second physical document editor window. So basically, I'm creating two editors for one document. That doesn't seem right. Again, it technically works, but it seems off.
If the expectation is that we have to implement IOleCommandTarget on our editor window and manually handle every single keystroke, shortcut, and mouse button and manipulate the underlying text buffer directly, then that is going to be the most depressing thing ever. That would mean they tout being able to use WPF, but then give us a document view without a WPF control that natively handles text editing even though they exist in the framework.
Sorry for the ridiculously long post, but I wanted to provide as much information as I possibly could about where I'm at and what I've tried.
Regarding CreateVsCodeWindowAdapter, see the "official" explanation how to make it work: https://developercommunity.visualstudio.com/t/projectionbuffertutorial-gives-error-in-dev16/498617

How Force browser to reload cached static file with versioning?

After deploying a new version of a website the browser loads everything from its cache from the old webpage until a hard, force refresh is done.
In ASP.NET MVC if the file becomes in Bundle, it handled by Optimization framework. a version added to your file link, and if a change occurs in your bundle's file a new token generate. follow below code :
for example, js file name is: datatables
when you put it in a bundle with the same name, you will see the
datatables?v=anY9_bo7KitrGnXQr8ITP3ylmhQe9NDzSjgLpLQWQFE1
as a file name.
change datatables and watch again the name of the file in the browser, surely it will change:
datatables?v=r8yhQBxKyDgrOGyqr1ndtdG92Ije09nqTY7yogrOSTk1
But there's two questions:
What we can do if our file wasn't in Bundle?
Is a way to force the browser to refresh cache?
we have one solution with some different way for implementation. we use above solution for it.
datatables?v=1
we can handle the version of the file, it's mean that every time that we change our file, change the version of it too. but it's not a suitable way.
another way used Guide, it wasn't suitable too, because each time it fetches the file and doesn't use from the browser cache.
datatables?v=Guid.NewGuid()
The last way that is the best Way is :
when file change occur , change version too. check follow code :
<script src="~/scripts/main.js?v=#File.GetLastWriteTime(Server.MapPath("/scripts/main.js")).ToString("yyyyMMddHHmmss")"></script>
by this way, when you change the file, LastWriteTime change too, so the version of the file will change and in the next when you open the browser, it detects a new file and fetch it.
Assuming you cannot use bundling for some reason, the solution suggested by the original poster is good enough, however it's better to put the logic inside a helper method.
It makes the code testable, it helps to change the logic without changing .cshtml , and also helps to not repeat the filename twice. Then you can have have a much cleaner code:
<script src="#Url.ContentWithVersion("~/scripts/main.js")"></script>
To do so, you can add ContentWithVersion extension method to the existing UrlHelper:
using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
public static class UrlHelperExtensions
{
public static string ContentWithVersion(this UrlHelper urlHelper, string path)
{
if (urlHelper == null)
throw new ArgumentNullException(nameof(urlHelper));
var result = urlHelper.Content(path);
var file = HttpContext.Current.Server.MapPath(path);
if (File.Exists(file))
result += $"?v={File.GetLastWriteTime(file).ToString("yyyyMMddHHmmss")}";
return result;
}
}

Reference to the right "System" in c# project

I am new to c# and visual studio and have run into some trouble.
I have created a project with references to "Windows" and ".Net" in visual studio because I want to test a little with smart cards.
The code:
using System;
using Windows.Devices.Enumeration;
using Windows.Devices.SmartCards;
class HandleSmartCard
{
public async void checkNumberOfSmartCards()
{
string selector = SmartCardReader.GetDeviceSelector();
DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(selector);
// return "2";
}
}
So far it looks fine. However I also want the project to be able to use
System.Windows.Forms; which I have used in a previos test.
I add reference to System.Windows.Forms; and try to create a form. However in that form when I try this:
Form prompt = new Form();
System.Windows.Forms.Button confirmation = new System.Windows.Forms.Button() { Dock = DockStyle.Bottom };
confirmation.Click += (sender, e) => { prompt.Close(); };
I get a red line under "Close" with the message:
Reference to type component claims it is defined in system but could
not be found.
System is referenced at top of file, but I am guessing it is the wrong type of system right?
Can I somehow use "both Systems" in one project so to speak?
I hope someone understands what I mean and can help me understand this.
You're most likely working on a UWP app. The API for UWP apps is a very small subset of the full .NET framework. You can find more information here
https://msdn.microsoft.com/en-us/library/windows/apps/mt185501.aspx
You're attempting to reference System.Windows.Forms which is not allowed in UWP applications.
Looks like you're trying to create a popup to ask the user something. For this, use the MessageDialog class.
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.popups.messagedialog.aspx

Why does any reference to Server.MapPath() kill my HttpContext Request.Params[]?

I am very much a novice in HttpHandlers. This is actually my first attempt at it.
I have this Ajax handler that responds to a jQuery ajax call in my web app front end:
public class ajaxMeetingHandler : IHttpHandler {
public void ProcessRequest(HttpContext context) {
string resultsJSON = "";
string requestType = context.Request.Params["requestType"];
if (!String.IsNullOrEmpty(requestType)) {
switch (requestType) {
case "RecentMXMeetings":
resultsJSON = SerialiseRecentMeetings(context, "Maintenance");
// SerialiseRecentMeetings() is a method in the class
// that works fine and is not included for brevity.
break;
// more cases (not included for brevity)
}
}
public bool IsReusable {
get {
return false;
}
}
}
}
And this works perfectly.
However, if I add either of these two statements anywhere in the code:
var x = context.Server.MapPath("/");
var y = HttpContext.Current.Server.MapPath("/");
...my Context.Request.Params[] collection becomes null, and IsNullOrEmpty(requestType) now sees requestType as null. In fact, ALL the Request.Params[] are null.
If I comment out those statements (and completely rebuild the solution) the thing goes back to working properly.
In the meantime, I am going to move the calls to MapPath() out to a static "RunTimeEnvironment" class so I can get the path I need from there without touching MapPath() from inside this HttpHandler. Is that a viable or recommended solution?
It turns out my problem was not related to the code itself, per se, but how I was running the project.
Visual Studio, when you click on the "Start Debug" button will start the solution at it's root document (ie, index.html). That is UNLESS the current open document is of a runnable type, such as .html. If your current open window is one of your class files (ie, .cs), it will not attempt to run the class file, but will start the debug session at your root document.
However, it WILL attempt to run a Generic Handler (.ashx) all by itself if that is the document you currently have open. And, by doing so, it was not starting at the index.html page which issues my ajax calls and sends parameters to the Handler. So, my Params collection was null because it was literally null. Running the .ashx by itself supplies no parameters.
So, the reason it worked after changing my call type from GET to POST and Back to GET again is because in doing so, I opened the index.html file to make that change, and when I started my debug session again, my current document was the index.html file, not the Generic Handler .ashx file.
I should probably lose a hundred reputations points just for making this dumb of a mistake. But in case it helps others, there it is.

Is it possible to use Gephi compiled with IKVM in a website?

I'm currently trying to load and use the Gephi Toolkit from within a .Net 4 C# website.
I have a version of the toolkit jar file compiled against the IKVM virtual machine, which works as expected from a command line application using the following code:
var controller = (ProjectController)Lookup.getDefault().lookup(typeof(ProjectController));
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
The three instances are correctly instantiated in a form similar to org.gephi.project.impl.ProjectControllerImpl#8ddb93.
If however I run the exact same code, with the exact same using statements & references, the very first line loading the ProjectController instance returns null.
I have tried a couple of solutions
Firstly, I have tried ignoring the Lookup.getDefault().lookup(type) call, instead trying to create my own instances:
var controller = new ProjectControllerImpl();
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
This fails at the line controller.newProject();, I think because internally (using reflector) the same Lookup.getDefault().lookup(type) is used in a constructor, returns null and then throws an exception.
Secondly, from here: Lookup in Jython (and Gephi) I have tried to set the %CLASSPATH% to the location of both the toolkit JAR and DLL files.
Is there a reason why the Lookup.getDefault().lookup(type) would not work in a web environment? I'm not a Java developer, so I am a bit out of my depth with the Java side of this.
I would have thought it possible to create all of the instances myself, but haven't been able to find a way to do so.
I also cannot find a way of seeing why the ProjectController load returned null. No exception is thrown, and unless I'm being very dumb, there doesn't appear to be a method to see the result of the attempted load.
Update - Answer
Based on the answer from Jeroen Frijters, I resolved the issue like this:
public class Global : System.Web.HttpApplication
{
public Global()
{
var assembly = Assembly.LoadFrom(Path.Combine(root, "gephi-toolkit.dll"));
var acl = new AssemblyClassLoader(assembly);
java.lang.Thread.currentThread().setContextClassLoader(new MySystemClassLoader(acl));
}
}
internal class MySystemClassLoader : ClassLoader
{
public MySystemClassLoader(ClassLoader parent)
: base(new AppDomainAssemblyClassLoader(typeof(MySystemClassLoader).Assembly))
{ }
}
The code ikvm.runtime.Startup.addBootClassPathAssemby() didn't seem to work for me, but from the provided link, I was able to find a solution that seems to work in all instances.
This is a Java class loader issue. In a command line app your main executable functions as the system class loader and knows how to load assembly dependencies, but in a web process there is no main executable so that system class loader doesn't know how to load anything useful.
One of the solutions is to call ikvm.runtime.Startup.addBootClassPathAssemby() to add the relevant assemblies to the boot class loader.
For more on IKVM class loading issues see http://sourceforge.net/apps/mediawiki/ikvm/index.php?title=ClassLoader

Categories