Get the current filename from a Visual Studio text adornment extension - c#

I'm new to VS extension development. I'm currently working with the text adornment sample in VS 2015 and have been able to get coloured boxes showing correctly. Now I want to extend the sample so the adornment only appears on certain file names.
Googling has said I can use ITextDocumentFactoryService.TryGetTextDocument interface with the IWpfTextView.TextBuffer property to get a filename. This sounds great. But I can't seem to actually get the interface.
In my class I have:
[Import]
public ITextDocumentFactoryService TextDocumentFactoryService = null;
But it is always NULL.
How can I get ITextDocumentFactoryService?
namespace Test
{
internal sealed class TestAdornment
{
[Import]
public ITextDocumentFactoryService TextDocumentFactoryService = null;
public TestAdornment(IWpfTextView view)
{
}
/// <summary>
/// Adds the scarlet box behind the 'a' characters within the given line
/// </summary>
/// <param name="line">Line to add the adornments</param>
private void CreateVisuals(ITextViewLine line)
{
// TextDocumentFactoryService is NULL
}
}
}

TextAdornmentTextViewCreationListener.cs
[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
internal sealed class TextAdornmentTextViewCreationListener : IWpfTextViewCreationListener
{
[Import]
public ITextDocumentFactoryService textDocumentFactory { get; set; }
//...
public void TextViewCreated(IWpfTextView textView)
{
new TextAdornment(textView, textDocumentFactory);
}
}
TextAdornment.cs
internal sealed class TextAdornment
{
private readonly ITextDocumentFactoryService textDocumentFactory;
private ITextDocument TextDocument;
//...
public TextAdornment(IWpfTextView view, ITextDocumentFactoryService textDocumentFactory)
{
//...
this.textDocumentFactory = textDocumentFactory;
//...
}
internal void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
{
var res = this.textDocumentFactory.TryGetTextDocument(this.view.TextBuffer, out this.TextDocument);
if (res)
{
//this.TextDocument.FilePath;
}
else
{
//ERROR
}
}
}

You got it via dependency injection.
As you only submitted 2 lines of code I suppose your context is set up, either explicitly by you, either implicitly by some environment who calls your code.
You should declare property instead of field
It should be public
Then automagically big brother will set it for you before you first access to it.
...or...
You can use constructor injection instead. Note: It is not you who will create your class.
private readonly ITextDocumentFactoryService _textDocumentFactoryService;
[ImportingConstructor]
internal YourClass(ITextDocumentFactoryService textDocumentFactoryService)
{
_textDocumentFactoryService = textDocumentFactoryService;
}

So in my case I needed to put the import statement into the AdornmentTextViewCreationListener. This implements IWpfTextViewCreationListener and is the one with the following decorating the class.
[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
Then I can add
private readonly ITextDocumentFactoryService _textDocumentFactoryService;
[ImportingConstructor]
to my class

Related

Need to avoid asserting for custom properties for MS controls

I have prepared the simple sample(WindowsForms) with custom control(ButtonAdv) which derived from Microsoft Button control.And implemented CodedUI Extension support for that custom control with my custom properties(BackColor and ForeColor,etc) by refferring the below blog,
https://blogs.msdn.microsoft.com/devops/2011/10/28/coded-ui-test-extension-for-3rd-party-windows-forms-controlshow-to/
All is working fine, when asserting my custom control the custom properties are added properly in CodedUITestBuilder property window.
Problem:
When i try to assert the Microsoft Button, there also my custom properties(BackColor,ForeColor) are displayed with empty values in CodedUITestBuilder property window.
I don't know why it is. Please anyone suggest me how to avoid of asserting custom properties for MicroSoft controls?
Here is minimum code of my implementation,
public class SfButtonAdv1:WinControl
{
public SfButtonAdv1(UITestControl control)
: base(control)
{
SearchProperties.Add(UITestControl.PropertyNames.ControlType, ControlType.Button.Name);
}
new public abstract class PropertyNames : WinControl.PropertyNames
{
public static readonly string BackColor = "BackColor";
public static readonly string ForeColor = "ForeColor";
}
}
public class SfButtonAdv : Button
{
public SfButtonAdv()
{
}
protected override AccessibleObject CreateAccessibilityInstance()
{
return new SfButtonAccessiblity(this);
}
}
public class SfButtonAccessiblity : ControlAccessibleObject
{
//
public override string Description
{
get
{
return this.sfButtonAdv.Style.BackColor.Name
+ "," + this.sfButtonAdv.Style.ForeColor.Name
}
}
}
Please let me know if you need any details further,
Thanks in Advance,

specify a object on a public method

I have the following method
public partial class formTabelasPsi : Form
{
private Form1 Opener { get; set; }
public formTabelasPsi(Form1 opener)
{
this.Opener = opener;
InitializeComponent();
}
public static void publicmethod1(string path)
{
//some code related to path
}
}
I want publicmethod1 to check a checkbox whenever this formTabelasPsi runs it.
I tried to specify it using formTabelasPsi.checkBox1.Checked = true; but the code says a object reference is required.
Maybe this is a newbiez question for most of you, but honestly, as a amateur programmer I didn't find this clearly anywhere.
The checkbox belongs to an instance of that form, you need to reference that instance in order to update it
public void publicmethod1(string path)
{
this.checkBox1.Checked = true;
}
The method also needs to belong to an instance of the form, you can find out more about instances here

Using custom application class for global variables in Xamarin c#

I'm using a custom application class for storing my global variables but i don't seem to be able to get it to work.
here is my class :
#if DEBUG
[assembly: Application(Debuggable = true)]
#else
[assembly: Application(Debuggable=false)]
#endif
internal class MyApp : Application
{
private Customer loginedCustomer;
private List<string> sefareshItems;
public Boolean isOnline { set; get; }
public MyApp(IntPtr handle, JniHandleOwnership ownerShip) : base(handle, ownerShip)
{
}
public override void OnCreate()
{
// If OnCreate is overridden, the overridden c'tor will also be called.
base.OnCreate();
}
public void SetLCustomer(Customer customer)
{
loginedCustomer = customer;
}
public Customer GetLCustomer()
{
return loginedCustomer;
}
public void SetItems(List<string> items)
{
sefareshItems = items;
}
public List<string> GetItems()
{
return sefareshItems;
}
}
and since i could find any documentation about using such class and by looking at the java examples both of these code gives me the "unable to cast from source to destination" exception
MyApp m = (MyApp)Application;
and
Myapp m=(MyApp)ApplicationContext;
could you help me figure this out?
and i have another question.is it a good practice to get or set variables using methods or using a public static one?
thank you
Application is a class definition.
You will need an instance of Application to cast as MyApp.
Make MyApp a static Class.
Make your method's static methods.
Then you can simply access Replace all references to Application with MyApp, and use it that way.

The name does not exist in the current context. Not seeing class

I am very new to C# coding, so this may be very simple. In my Site.Master.cs, I have the following code:
GetLoggedInUserProperties();
lblLoginUser.Text = string.Format("Welcome {0}", Session[SessionVars.UserName]);
In a class file, I have put the following in a Public Class:
void GetLoggedInUserProperties()
{
string sLoginId = Program.ExtractUserName(HttpContext.Current.Request.ServerVariables["LOGON_USER"]);
HttpContext.Current.Session[SessionVars.LoginId] = sLoginId;
VerifyInAD(sLoginId);
}
There are no errors in the class file, but my Site.Master.cs cannot find the code in the class file.
I am sure there is a better way to do this, so feel free to let me know. Also, the lblLoginUser does not seem to work either. It has the same error. I have tried recreating the label and deleting the designer file (which never came back). Not sure if this is related or not.
Thank you.
You need to make your methods public or protected to be visible from the markup. So if you want to reference GetLoggedInUserProperties() from the markup, you'll need to change your method declaration to something like this.
protected void GetLoggedInUserProperties()
{
}
Make your method public
Here your class
public class ClassName
{
public void GetLoggedInUserProperties()
{
}
}
public MainWindow()
{
InitializeComponent();
ClassName instance = new ClassName();
instance.GetLoggedInUserProperties();
}
Or make your class static and call your method :
public static class ClassName
{
public static void GetLoggedInUserProperties()
{
}
}
public MainWindow()
{
InitializeComponent();
ClassName.GetLoggedInUserProperties();
}

Function returning list of different possible children classes

I have a binding source which can be bound to a list of A or a list of B. Depending if it's A or B, when I click "Save" I want to call the save method of the appropriate repository.
I was able to create this method to check if any list is dirty and needs saving:
private static bool IsDirty<T>(TList<T> list) where T : IEntity, new()
{
foreach (var entity in list)
{
if (entity.IsDirty)
return true;
}
return false;
}
However, I am having a problem with the following:
var list = CurrentTList<A>();
and
private TList<T> CurrentTList<T>() where T: IEntity, new()
{
switch (currentRatesTable)
{
case RatesTables.A:
return (TList<T>) _bindingSourceMaster.List;
case RatesTables.B:
return (TList<T>) _bindingSourceMaster.List;
default:
return null;
}
}
Is this the best way to get my current list from the data source? I would like to avoid using a switch like so, as it doesn't look right to me:
switch (currentRatesTable)
{
case Form1.RatesTables.A:
var list = CurrentTList<A>();
case Form1.RatesTables.B:
var list = CurrentTList<B>();
// ...
}
Yeah, as Sayse says, you need yourself an interface and/or an abstract class. If there's a lot of shared code, you can just start with the latter. Here's something riffed on from an old test project. It takes a different approach (each item in the collection is what's relevant as the 'dirty' thing, and there are excised methods that would search the collection for those), but you should be able to adapt as needed:
[DataContract]
public abstract class Dirty : Object
{
protected bool _isdirty;
public bool IsDirty
{
get { return _isdirty; }
set
{
_isdirty = value;
}
}
public abstract class DataStore<T> where T : Dirty
{
private string _path;
private string _tempFile;
protected DataStore(string path, string tempfile)
{
_path = path;
_tempFile = tempfile;
}
}
So DataStore held the logic to manipulate those lists. The idea for me was both classes that inherited from Dirty were being serialized to JSON, so as long as their members had the right attributes they all got properly serialized, and thus there was no custom logic for each class for its storage. Thus, all they had to do to create their datastore was:
[DataContract]
public class Account : Abstracts.Dirty
{
#region DataStore fields and singleton
private static volatile StoreClass _store = new StoreClass();
protected static StoreClass Store
{
get
{
return _store;
}
}
/// <summary>
/// Store is the data store for the Account class. This holds the active list of Accounts in a singleton, and manages the push/pull to the JSON file storage.
/// </summary>
protected class StoreClass : Abstracts.DataStore<Account>
{
#region Singleton initialization and Constructor
public StoreClass()
: base("accounts.json", "TEMP_accounts.json")
{
}
#endregion
}
}
I cut out a few thousand lines on this project just from the datastore, but it was pretty crazy. The basic idea is to build the logic you need into the DataStore class to save a list, and aim how you save/load it via how you call its constructor from the StoreClass child.

Categories