Child Form cannot find text file - c#

I have created a boolean algebraic simplifier. It simplifies expressions and I am content with it. However, I am trying to add a feature that allows users to check if two expressions are equivalent. For this I have created a new form that allows the user to input two expression by clicking buttons. To do this, I thought it best to simplify both expressions and then compare the two for equivalency. As I have got lots of subroutines and code that works for simplification in another form, I thought making the form a child form of the form with the code in would allow me to call the subroutines instead of copying them onto the form. I have made these protected in the parent form. I have inherited like so:
public partial class Expression_Equivalency_Form : Expression_Simplifier
However, when I click onto the form designer, this error appears and I cannot view the graphical interface of the form:
"Could not find file File Path"
The file is in the debug folder which is within the bin folder within the folder containing the program and is recongised in the parent class. The file is read from and appeneded by the parent form without issue. I have tried to research this but have been unable to find a solution. Does anyone know one?
I have read to the file and appended to it. I have also used the following code to remove any blank lines from my text file:
File.WriteAllLines("PreviousExpressionInputs.txt",
File.ReadAllLines("PreviousExpressionInputs.txt").Where(l => !string.IsNullOrWhiteSpace(l)));
Code that writes to the file:
using (BinaryWriter Writer = new BinaryWriter(File.Open("PreviousExpressionInputs.txt",
FileMode.Append)))
{
Writer.Write(expressionandanswertowritetotextfile);
}
Code that reads from the file:
foreach (string line in File.ReadLines("PreviousExpressionInputs.txt"))
{
try
{
LinesInFile.Add(line);
}
catch (Exception)
{
}
}

Consider following facts:
When you open a form in design mode, the constructor of its base class will run.
When you look for a relative file name, the path will be resolved relative to the current working directory of the application.
When the form is in design mode, the current application is Visual Studio and its working directory is where the devenv.exe is located.
It describes why you cannot find your text files. Because you have some code in the constructor of your base form(or fir example load event handler of the base form) which looks for the file and since the filename is relative, its looking for the file in the Visual Studio working directory and could not find file.
How to prevent the problem? Check DesignMode property to prevent running the code:
public partial class MyBaseForm : Form
{
public MyBaseForm()
{
InitializeComponent();
}
private void MyBaseForm_Load(object sender, EventArgs e)
{
MessageBox.Show("This will show both in run-time and design time.");
if (!DesignMode)
MessageBox.Show("This will show just in run-time");
}
}
Create the derived form and open it in designer to see what happens:
public partial class Form1 : MyBaseForm
{
public Form1()
{
InitializeComponent();
}
}
To learn more about how designer works take a look at this post.

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

uwp inheriting from base page giving compile errors

I am trying to inherit from a base page instead of Normal Page control of XAML but Visual Studio is giving me compile time errors that OnNavigatedTo method not found to be overridden.
I am doing this because I have multiple pages with a lot of similar code and I want to write that code just once, so I want to write that code in parent class and then inherit all pages from that parent class, I followed guidelines as stated on multiple resources on internet and below is my code.
Parent Class:
public class VideoParentPage : Page
{
}
Child Class (AllVideoPage.xaml.cs):
public sealed partial class AllVideosPage : VideoParentPage
{
public AllVideosPage() : base()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
SetBanner();
}
}
XAML in file AllVideosPage.xaml:
<local:VideoParentPage
xmlns:local="using:Fluent_Video_Player.Views.Shared"
...some unrelated XAML code...
</local:VideoParentPage>
Note: I have used all necessary using statement in C# classes.
You should try cleaning the solution Build > Clean Solution, closing VS, removing the remaining bin and obj folders and then compiling the app again.

Multiple Ribbons in Outlook Addin

I have an Outlook addin where I need to display a ribbon in the main Outlook window and in the Mail Read window as well. To do this I have added two ribbon xml files with the right markups in them. I then added a C# class that implements the Office.IRibbonExtensibility interface where I have implemented the GetCustomUI method which returns the right XML. Finally I did this in the ThisAddIn.cs class
protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
try
{
_ribbon = new Ribbon();
return _ribbon;
}
catch (Exception e)
{
}
return null;
}
So far so good. The ribbons load and everything shows in correct place.
Now the problem is that this Ribbon.cs file is getting rather huge as all the callbacks live in this file. Is there a way to split the callbacks into multiple classes? So if I have a Ribbon1.xml and RIbbon2.xml can I have equivalent Ribbon1.cs and Ribbon2.cs?
OK so as it turns out this is really not possible in the VSTO model. You can really only have one class which must have all the event handlers in it. The recommended approach is to use partial classes and split the code between multiple code files.

Losing UserControl when editing winForm VS2012

I have a Form called EmployeeForm inside this form i'm including some UserControl and when I edit EmployeeForm every UserControl inside the form are lost.
This picture show a diff between TFS(left) and Local(right) file, after modifying the name of a combobox
Example of this.ucEmployeeKeyOne :
public partial class Employee_EmployeeKeyOneRelationUC
: Employee_EmployeeKeyOneRelation_GenericUC
{ [other Code Here] }
public class Employee_EmployeeKeyOneRelation_GenericUC
: RelationUC<MyObject>
{ }
and the definition of RelationUC :
public partial class RelationUC<T>
: DataUserControlBase
{ [other Code Here] }
public partial class DataUserControlBase
: UserControlBase
{ [other Code Here] }
public partial class UserControlBase
: System.Windows.Forms.UserControl, MyInterfaceHere
{ [other Code Here] }
All UserControl i'm losing are inherited from RelationUC<T>. Does the generic type of RelationUC may cause the problem?
For the Vs designer to load the controls, the control should be able to initialize including all public properties and you must have a empty constructor. If you don't have an empty constructor or have properties that are returning from the inherited nullable class, it is most likely the the designer will crash.
To Debug this,
1) open you project in VS but do not open the file that contains the controls yet;
2) open another VS and attach the process of VS that your project is opened;
3) set the break on exceptions (short cut 'CTRL + D, CTRL +E' ) to all (once you become familiar with what exception the designer is throwing, you can set that exception only.);
4) Go to the VS with you project and open the file that contain your user control. when the exception is thrown, the second VS will catch it and tell you exactly why and where.

Is this the proper way to obtain a drag and drop file for the exe application created in C#?

Pretty much exactly what the title says. I created an exe windows form program in C# and i found how to obtain the file name and path that was dragged and dropped onto the exe. Well is this the proper way to obtain the file?
public partial class Form1 : Form
{
public static String file;
public Form1()
{
foreach (String arg in Environment.GetCommandLineArgs())
{
file = arg;
}
InitializeComponent();
label1.Text = file;
}
}
}
It does work and if i run the program itself, it gives me the file path and name of the exe itself. But when dragging and dropping to the exe, it gives me the file that i dropped. Is this the proper way to do it?
In general, GetCommandLineArgs may or may not contain path to executable as first argument. But in most cases - first argument will be your exe.
So, second, third and so on arguments will contains dropped files.
Hm, thought command line passed to the main method of main class in C#, no?

Categories