I have UserControl displaying file information. And I want to see test file information in visual studio designer using view-model mock. Here is XAML:
<Label Content="{Binding DateCreated}"/>
View-model:
internal class ViewModel
{
public ViewModel(string pathToFile)
{
var file = new FileInfo(pathToFile);
this.DateCreated= file.CreationTime.ToShortDateString();
}
public string DateCreated{ get; set; }
}
In design-time I see real file information in designer using view-model mock class:
internal class ViewModelMock : ViewModel
{
public ViewModelMock() : base(#"D:\Images\mock.png")
{
}
}
I plug mock into xaml via d:DataContext and d:DesignInstance:
<UserControl ...
xmlns:mocks="clr-namespace:Company.Product.Mocks"
d:DataContext="{d:DesignInstance mocks:ViewModelMock, DesignTimeCreatable=True}">
It works, but the problem is in this #"D:\Images\mock.png" hardcoded value. As soon as solution powered by TFS, I need to place the image into the project and reference this image from ViewModelMock, relative to project path.
How can I do that?
Simple methods like getting current working directory gives 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE', I guess because this is location of XDesProc.exe which responsible for visual studio designer.
Currently I'm using EnvDTE method described in this questions:
var solutionFullName = ((EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.12.0")).Solution.FullName;
var projectPath = Path.Combine(Path.GetDirectoryName(solutionFullName), "ProjectFolderName");
But this has almost the same problem - hardcoded "VisualStudio.DTE.12.0" constant (which means Visual Studio 2013), so I'm still trying to find better solution.
Related
I've got a custom user control with a public property that I'd like to be able to set in XAML. Here it is below.
TestControl.xaml
<UserControl x:Class="Scale.Controls.TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
TestControl.xaml.cs
using System.Windows.Controls;
namespace MyProject.Controls
{
public partial class TestControl : UserControl
{
public string TestMe { get; set; }
public TestControl()
{
InitializeComponent();
}
}
}
Then, in my MainWindow.xaml file, I try to include this:
<controls:TestControl TestMe="asdf" />
However, even though Visual Studio autocompletes the TestMe property, I then see things with a squiggly underline that says "The member "Test Me" is not recognized or is not accessible," as seen below.
I could have sworn I've done something like this before in other projects. How can I access (i.e. set) the public properties via XAML like this?
Visual Studio 2017
I had exactly the same problem. It was compiling one day ... and then it wasn't. I wasn't using DependencyProperty which shouldn't be needed as above. The properties were appearing in Intellisense but gave the same message when inserted. I cleaned, built, rebuilt, restarted VS, rebooted etc. All to no avail.
Last ditch try ... I removed all the offending attributes and got a clean compile. Then I put them back and it compiled. I really wasn't expecting that. Somehow VS had gotten its knickers in a twist.
If you are using VS2017, try to delete bin and obj folders in all projects of your solution, clean the solution and build again. It works for me !
You need to declare your property as Dependency Properties
namespace MyProject.Controls
{
public partial class TestControl : UserControl
{
//Register Dependency Property
public static readonly DependencyProperty TestMeDependency = DependencyProperty.Register("MyProperty", typeof(string), typeof(TestControl));
public string MyCar
{
get
{
return (string)GetValue(TestMeDependency);
}
set
{
SetValue(TestMeDependency, value);
}
}
public TestControl()
{
InitializeComponent();
}
}
}
Change the build target from AnyCPU to either x86 or x64. Unsure why AnyCPU does not work.
I know this is late but I just ran into this issue on VS 2020.
I tried all 3 options listed above and none of them worked including the CPU build.
I ended up having to right-click each project, clean, and rebuild. Then it solved the issue...
Really annoying this is still an issue.
In my case, there're no errors originally, after I modify my class, there're some errors in my class then the Xaml Error member is not recognized show. After solving errors in my class, I pass building the projects, all projects are built without errors, but the errors still show in the Error List Window. In the end, I restart Visual Studio, the errors disappear.
I faced this problem with my VS2022, I just removed WindowsBase reference, and it worked.
instead of setting multiple dependency properties for the control, I would use reflection.
public static readonly DependencyProperty UserControlProperty = DependencyProperty.Register("UserControl",
typeof(object), typeof(CustomUserControl), new PropertyMetadata(null));
public object UserControl
{
get { return GetValue(UserControlProperty); }
set { SetValue(UserControlProperty, value); }
}
I have really strange problem. I've created WPF project in 2012 or 2013 VS it doesn't matter. I use .NET 4.5.
I add a new Activity (Workflow class) to that project. Its name is CustomActivity.
Then I add a new class that has got an attached property, example below:
public class AttachedObject : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.RegisterAttached(
"Name",
typeof(string),
typeof(AttachedObject),
new FrameworkPropertyMetadata(
string.Empty,frameworkPropertyMetadataOptions.AffectsRender));
public static void SetName(ContentControl element, string value)
{
element.SetValue(NameProperty, value);
}
public static string GetName(ContentControl element)
{
return (string)element.GetValue(NameProperty);
}
}
The last step is to change MainWindow class that way:
public MainWindow()
{
InitializeComponent();
var activity = new CustomActivity();
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1;assembly=WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ContentControl wpfApplication1:AttachedObject.Name="MainArea"/>
</Grid>
</Window>
The problem is it doesn't compile because of below error:
Error 1 The type or namespace name 'CustomActivity' could not be found (are you missing a using directive or an assembly reference?) WpfApplication1\MainWindow.xaml.cs 13 32 WpfApplication1
CustomActivity has a default namespace. In obj folder there is CustomActivity.g.cs generated, so I have no idea what's going on.
It's 100% reproducible. When I remove using of CustomActivity or using of AttachedObject from xaml then the problem disappear.
Try replacing this:
xmlns:wpfApplication1="clr-namespace:WpfApplication1;assembly=WpfApplication1"
with this
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
The error you're seeing is due to a "known" issue in WPF applications that xaml namespaces that reference clr namespace from current assembly your in don't require the full assembly qualified name. If you were to declare a xaml namespace that references a clr namespace from another assembly, than you would have to specify the full name (with the ;[assemblyname] syntax).
Workflow Foundation has nothing to do with it.
EDIT:
Didn't realize it was a xaml activity.
But still, you can make it work, maybe, with a few hacks, but I wouldn't recommend it.
The reason you get that error is due to the different code generation and build action VS uses when creating xaml artifacts for WPF (Page):
System.Windows.Application.LoadComponent(this, resourceLocater);
and when creating xaml activities (XamlAppDef):
typeof(CustomActivity).Assembly.GetManifestResourceStream(resourceName);
If you turn your CustomActivity xaml build action to Page, the whole thing will compile - but i'm guessing something else might be broken someplace else...or not, who knows. My guess is that these two kinds of xaml were not meant to live together in a VS WPF application project template. But you can still define activities in a WF activity library, that way your activities will also be more easily reusable for other projects, WPF, console or even services.
I have the same issue under Visual Studio 2017.
The problem in my case is that Visual Studio is not compiling the Workflow activities before the code that use them.
To fix it, what I did is to move all workflows to other project dll, so visual Studio is forced to compile the workflows before the classes that make use of them.
I created a new VSIX extension project in Visual Studio 2012, and wrote a MEF classifier (as a test) that should simply highlight all text in a .mylang file. Here are the relevant parts of my .NET 4.5 code:
internal static class MyLangLanguage
{
public const string ContentType = "mylang";
public const string FileExtension = ".mylang";
[Export(typeof(ClassificationTypeDefinition))]
[Name(ContentType)]
[BaseDefinition("code")]
internal static ContentTypeDefinition MyLangSyntaxContentTypeDefinition = null;
[Export]
[FileExtension(FileExtension)]
[ContentType(ContentType)]
internal static FileExtensionToContentTypeDefinition MyLangSyntaxFileExtensionDefinition = null;
}
[Export(typeof(IClassifierProvider))]
[ContentType(MyLangLanguage.ContentType)]
[Name("MyLangSyntaxProvider")]
internal sealed class MyLangSyntaxProvider : IClassifierProvider
{
[Import]
internal IClassificationTypeRegistryService ClassificationRegistry = null;
public IClassifier GetClassifier(ITextBuffer buffer)
{
return buffer.Properties.GetOrCreateSingletonProperty(() => new MyLangSyntax(ClassificationRegistry, buffer));
}
}
internal sealed class MyLangSyntax : IClassifier { }
Here is the full code.
These are the relevant parts from my source.extension.vsixmanifest file. Based on suggestions and similar files I found across the web, I added the dependency on MPF and the two assets.
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<!-- ... -->
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="4.5" />
<Dependency d:Source="Installed" Id="Microsoft.VisualStudio.MPF.11.0" DisplayName="Visual Studio MPF 11.0" Version="[11.0,12.0)" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
</Assets>
</PackageManifest>
I also tried a version 1.0 manifest:
<?xml version="1.0" encoding="utf-8"?>
<Vsix Version="1.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
<!-- ... -->
<References />
<Content>
<MefComponent>|%CurrentProject%|</MefComponent>
</Content>
</Vsix>
When I run it, it starts an experimental instance of Visual Studio 2012, and the Extensions and Updates window shows that my extension is active. However, it does not do anything when I load or create a .mylang file. Any exceptions I throw (as a test) from my extension are never thrown. Breakpoints are never hit, and get an exclamation mark with the following warning:
The breakpoint will not currently be hit. No symbols have been loaded for this document.
It feels as if my extension is never really loaded at all. My problem is similar to this problem and this problem, but I'm using Visual Studio 2012 which uses a new VSIX manifest format.
What I know:
I can find my DLL and VSIX file in the %localappdata%\Microsoft\VisualStudio\11.0Exp\Extensions\MyLang\VSIXProject1\1.0 folder, so I know they are copied.
Their timestamp corresponds to when I last built the project, so I know they are up-to-date.
Project Properties > Debug > Start external program: is already automatically set to C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe, and the Command line arguments were automatically set to /rootsuffix Exp.
The Visual Studio log (created with the /log option) has two entries related to my extension: Successfully loaded extension... and Extension is enabled....
My DLL does not appear on the Modules tab (list of all loaded DLLs) of the debugging Visual Studio, while some (not all) other extensions do appear.
It doesn't get loaded in Visual Studio 2012 or 2010 both on my laptop and my desktop PC.
What I've tried:
Set <IncludeAssemblyInVSIXContainer> to true in the .csproj file, per this suggestion, but it did not make any difference.
I can't add the line <MefComponent>|%CurrentProject%|</MefComponent> to the source.extension.vsixmanifest file as it uses a different format (2.0) than VSIX projects for previous versions of Visual Studio (1.0).
This suggestion (setting IncludeAssemblyInVSIXContainer and friends in my .csproj to true) but it does not make a difference. And my breakpoints are still showing the warning and not being hit.
Reset the VS Experimental instance using the Reset the Visual Studio 2012 Experimental Instance shortcut in the Start Menu, as per this suggestion. It didn't make a difference.
How can I at the very least be sure my VSIX MEF extension is loaded and works? And if possible, how can I make by breakpoint work and debug it?
Edit: The problem is you've improperly exported your ContentTypeDefinition as a ClassificationTypeDefinition. You should use the following instead:
[Export] // <-- don't specify the type here
[Name(ContentType)]
[BaseDefinition("code")]
internal static ContentTypeDefinition MyLangSyntaxContentTypeDefinition = null;
Here's my two guesses right now:
Try removing the following line from your vsixmanifest. I assume you do not have a class in your project that extends Package, in which case Visual Studio might be refusing to load your package due to the following Asset line (your extension does not actually provide this asset).
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
If that fails, try replacing your current source.extension.vsixmanifest with one written to the old schema (version 1.0). I know this form still works in Visual Studio 2012 because all ~20 extensions I work on (with >10 public releases) use the old schema.
280Z28 solved the problem! For completeness, this is the full tried and tested code that will create a super simple VSIX Visual Studio MEF extension that colors all text in a .mylang file blue (or whatever the current keyword color is).
How to create a simple coloring MEF VSIX extension
Make sure you have the Visual Studio SDK installed. (VS2010 SP1 SDK, VS2012 SDK)
Create a new VSIX Project(From the template under Installed → Templates → Visual C# → Extensibility.)
Enter something in the Author field of the VSIX manifest editor, then save and close it.
Add references to the following libraries,version 10.0.0.0 for VS2010, or 11.0.0.0 for VS2012:
Microsoft.VisualStudio.CoreUtility.dll
Microsoft.VisualStudio.Language.StandardClassification.dll
Microsoft.VisualStudio.Text.Data.dll
Microsoft.VisualStudio.Text.Logic.dll
Microsoft.VisualStudio.Text.UI.dll
Microsoft.VisualStudio.Text.UI.Wpf.dll
Add a reference to the following library:
System.ComponentModel.Composition.dll version 4.0.0.0
Create and add a new code file MyLang.cs, and copy-and-paste the code below in it.
Edit source.extension.vsixmanifest as XML.
For Visual Studio 2010, add the following XML just before the closing tag </Vsix>, and save:
<Content>
<MefComponent>|%CurrentProject%|</MefComponent>
</Content>
(If there is already an empty <Content/>, remove it.)
For Visual Stuio 2012, add the following XML just before the closing tag </PackageManifest>, and save:
<Assets>
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
</Assets>
(If there is already an empty <Assets/>, remove it.)
Only for Visual Studio 2010:
Unload the VSIX project (right-click the project → Unload project).
Edit the .csproj project file (right-click the project → Edit MyProject.csproj).
Change the value at <IncludeAssemblyInVSIXContainer> to true.
Save and close the file.
Reload the VSIX project (right-click the project → Reload project).
Now build and run it. When you load a .mylang file, all text should be colored blue (or whatever the default keyword color is).
MyLang.cs
using Microsoft.VisualStudio.Language.StandardClassification;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace VSIXProject1
{
internal static class MyLangLanguage
{
public const string ContentType = "mylang";
public const string FileExtension = ".mylang";
[Export]
[Name(ContentType)]
[BaseDefinition("code")]
internal static ContentTypeDefinition MyLangSyntaxContentTypeDefinition = null;
[Export]
[FileExtension(FileExtension)]
[ContentType(ContentType)]
internal static FileExtensionToContentTypeDefinition MyLangSyntaxFileExtensionDefinition = null;
}
[Export(typeof(IClassifierProvider))]
[ContentType(MyLangLanguage.ContentType)]
[Name("MyLangSyntaxProvider")]
internal sealed class MyLangSyntaxProvider : IClassifierProvider
{
[Import]
internal IClassificationTypeRegistryService ClassificationRegistry = null;
public IClassifier GetClassifier(ITextBuffer buffer)
{
return buffer.Properties.GetOrCreateSingletonProperty(() => new MyLangSyntax(ClassificationRegistry, buffer));
}
}
internal sealed class MyLangSyntax : IClassifier
{
private ITextBuffer buffer;
private IClassificationType identifierType;
private IClassificationType keywordType;
public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
internal MyLangSyntax(IClassificationTypeRegistryService registry, ITextBuffer buffer)
{
this.identifierType = registry.GetClassificationType(PredefinedClassificationTypeNames.Identifier);
this.keywordType = registry.GetClassificationType(PredefinedClassificationTypeNames.Keyword);
this.buffer = buffer;
this.buffer.Changed += OnBufferChanged;
}
public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan snapshotSpan)
{
var classifications = new List<ClassificationSpan>();
string text = snapshotSpan.GetText();
var span = new SnapshotSpan(snapshotSpan.Snapshot, snapshotSpan.Start.Position, text.Length);
classifications.Add(new ClassificationSpan(span, keywordType));
return classifications;
}
private void OnBufferChanged(object sender, TextContentChangedEventArgs e)
{
foreach (var change in e.Changes)
ClassificationChanged(this, new ClassificationChangedEventArgs(new SnapshotSpan(e.After, change.NewSpan)));
}
}
}
Set <IncludeAssemblyInVSIXContainer> to true in the .csproj file, per
this suggestion.
I had exactly the same problem and this solved it. Do a full rebuild.
When I modify my resource file (.resx) add text or modify, the constructor of my resource always go to internal and after that, when I run my silverlight I have an error in my binding XAML.
Is there a way to avoid this scenario? I need to go in the designer of my resource and put the constructor to public to solve the problem
I use my resource like this in my xaml file
<UserControl.Resources>
<resources:LibraryItemDetailsView x:Key="LibraryItemDetailsViewResources"></resources:LibraryItemDetailsView>
</UserControl.Resources>
<TextBlock FontSize="12" FontWeight="Bold" Text="{Binding Path=FileSelectedText3, Source={StaticResource LibraryItemDetailsViewResources}}"></TextBlock>
Another way to do this without code changes is as below. Worked well for me.
http://guysmithferrier.com/post/2010/09/PublicResourceCodeGenerator-now-works-with-Visual-Studio-2010.aspx
You can create a public class that exposes the resources through a property:
public class StringsWrapper
{
private static LibraryItemDetailsView _view = null;
public LibraryItemDetailsView View
{
get
{
if (_view == null)
{
_view = new LibraryItemDetailsView();
}
return _view;
}
}
}
Then in your XAML you can access your resource:
<UserControl.Resources>
<StringsWrapper x:Key="LibraryItemDetailsViewResources"></StringsWrapper>
</UserControl.Resources>
<TextBlock FontSize="12" FontWeight="Bold" Text="{Binding Path=View.FileSelectedText3, Source={StaticResource LibraryItemDetailsViewResources}}"></TextBlock>
This way the resx constructor can be internal!
Well, what I did was to add a command line utility to pre-build event of each Silverlight project that replaces each internal string with public :)
You can edit pre-build and post-build events by: Right-clicking on a project -> Properties -> Build Events.
I used a utility called RXFIND, it's free and can replace a string within selected files using a RegEx regular expression.
Here's the command line I'm using:
"$(SolutionDir)ThirdParty\rxfind\rxfind.exe" "$(ProjectDir)Resources\*.Designer.cs" "/P:internal " "/R:public " /Q /B:2
Please note, that all my resources are located under Resource directory within each project and the command line utility resides in \ThirdParty\rxfind directory
I also have the same error. To solve the problem I just created a public class that inherits from the class representing the resources file, knowing that it must also be public class this is my exep:
public class TrackResourceWrapper : TrackResource
{
}
with:
TrackResourceWrapper is inheriting class
TrackResource is the class which is located in the code resource file behind (public class)
Simply:
Add a new class that inherits from the resource class
In the App.xaml file, modify the resource class which you created
Done!
The reason for this is that you shouldn't be instantiating the class yourself. You should instead always use ConsoleApplication1.Resource1.ResourceManager which itself instantiates the class for you.
Here, ConsoleApplication1 is the name of your assembly and Resource1 the name of your resource file.
I created a macro to do this for me for each file I edit. I still have to remember to run it, but it's a lot quicker. Please see my post.
I have a XAML form for use in my application, and I have subclassed the Frame class to create my own, and edited the interface to specify my own class for the content (as I need to access properties on the content for data binding).
The problem comes then in the designer that the compiler says it cannot create an instance of my control - I've tried to do some designer checks on the offending property bit but that didnt work either.
How can I get the control to display? Works fine at runtime...
XAML:
<Grid Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<views:PageFrame Name="Content_MainPage" Frame.NavigationUIVisibility="Hidden"/>
</Grid>
CS:
public new BaseView Content
{
get
{
if (DesignerProperties.GetIsInDesignMode(this))
{
return new BaseView();
}
else
{
return (BaseView)base.Content;
}
}
set
{
if (DesignerProperties.GetIsInDesignMode(this))
{
base.Content = new BaseView();
FrameTitle = "design mode";
}
else
{
base.Content = value;
FrameTitle = value.Title;
}
}
}
I came across a similar problem when creating my own Panel class.
Is your PageFrame class defined in the same assembly that your XAML lives in?
I found the only way I could get this to work was to move my "PageFrame" class into a new assembly. From memory I think I even had to build that assembly ahead of time, so that the assembly could be referenced via a file reference (as opposed to a project reference).
I hated this solution, so I hope you find a cleaner one :)
Have you got VS2008 SP1 installed? I had hoped MS would fix this bug. I haven't tried removing my workaround to check...
Its in the same assembly - and yes I have VS2008 SP1 installed too. Not that removing the above property lets it work fine from a vs point of view, but obviously not from my point of view!
I will give this a go - thanks Antony.