IntelliSense for Data Binding not working - wpf

After a couple of hours trying to debug an issue with data-binding that was caused by a mistyped property in a Binding extension. Once I noticed the mistake, the realization that if IntelliSense was available I may have not made the mistake in the first place. As a Visual Studio user who is used to error/warnings when mistyping a name; perhaps I'm spoiled, but the lack of IntelliSense led to the error.
I did some research and I found that Intellisense for Data Binding is available is Visual Studio 2013 which I'm using (Ultimate edition). I tried creating a simple WPF app following the second example in the blog. Firstly, There appears to be an error in the second example in the blog that resulted compiler error. Prefixing the Type=ViewModel:MainViewModel attribute with d: fixed the compiler error, yet the properties of my View-Model class are still not showing in the Intellisense menu. My code is below and in GitHub.
MainViewModel.cs:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace IntelliSenseForDataBinding
{
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
Greeting = "Hello World";
Answer = 42;
}
private string _Greeting;
public string Greeting
{
get { return _Greeting; }
set { _Greeting = value; OnPropertyChanged(); }
}
private int _Answer;
public int Answer
{
get { return _Answer; }
set { _Answer = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainWindow.xaml:
<Window x:Class="IntelliSenseForDataBinding.MainWindow"
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="450"
d:DataContext="{d:DesignInstance Type=MainViewModel, IsDesignTimeCreatable=True}"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>
MainWindows.xaml.cs:
using System.Windows;
namespace IntelliSenseForDataBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new MainViewModel();
InitializeComponent();
}
}
}
Here's the evidence that is not working:
I would expect to see an item for the 'Greeting' property in the IntelliSense menu. Any suggestions on why it's not there? I've also tried resetting the Visual Studio settings to default, just in case.
In addition, any suggestions on additional methods for preventing or detected mistyped property names in Binding attributes?

I opened your GitHub project in Visual Studio 2013 and I got the same behavior; no IntelliSense for bindings.
The design data is the key to the binding resolution which is failing, so I recommend this:
Add your project namespace to your Window element: xmlns:local="clr-namespace:IntelliSenseForDataBinding" which can help resolve the location of VM.
Change your d:DataContext to use the local namespace instead of d:Type, essentially providing the location of the type you're trying to use: d:DataContext="{d:DesignInstance local:MainViewModel, IsDesignTimeCreatable=True}"
Clean, Build, and Test
Proof:

I know I am late, but Kcvin's answer really helped me a lot and I would like to add that some classes can also use DataType that helps IntelliSense do its magic.
example:
<DataTemplate x:Key="ItemTemplate" DataType="entities:Item">
<Grid Height="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Text=""
Style="{StaticResource MediumIconStyle}"
Margin="{StaticResource XSmallLeftMargin}"
AutomationProperties.Name="List item icon" />
<StackPanel
Grid.Column="1"
Margin="{StaticResource SmallLeftMargin}"
VerticalAlignment="Center">
<TextBlock Style="{StaticResource ListTitleStyle}" Text="{Binding Name}" />
<TextBlock Style="{StaticResource ListSubTitleStyle}" Text="{Binding Description}" />
</StackPanel>
</Grid>
</DataTemplate>
I hope this helps someone in the future.

UPDATE:
This issue has been resolved in the latest version of Visual Studio (v16.8 and higher). Simply upgrade to the latest version. Hopefully this issue stays fixed.
EDIT:
The visual studio team is currently yet to provide a stable solution to this issue. According to this ticket a fix is available in Visual Studio 16.8 Preview 3. For the meantime, you can consider other creative workarounds present.
If none of the answers here worked for you, a possible way of troubleshooting this issue would be to use the Visual Studio Designer.
Take your caret to a XAML element.
Click on the Properties Tab (or simply press F4)
Go to the DataContext property. If it appears to be empty, try pressing the New button.
If your designer gracefully crashes (like mine did), try to do more debugging from there.
In my case the error looked like this: Could not resolve type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' in assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Which led me to this question and the installation of the System.Runtime nuget, and a few other changes.
Once the Properties tab is able to correctly identify your ViewModel Intellisense should start working property. If it doesn't, try restarting Visual Studio.

Update Visual Studio to the latest versions, if you are using VS2019.
This will resolve the issue.

Related

Xaml: design a layout with dynamically visible components

In a mvvm application some areas inside a window (in reality it is a UserControl inside MainWindow) are dynamically displayed according to the user selections.
The changing blocks are inside Stackpanels, I have 4 of them and only one at a time is displayed. This is accomplished binding Visibility to a bool property and using the BooleanToVisibilityConverter.
I put all the alternate StackPanel inside parent control. It works correctly, but during design phase in Visual Studio I see all of them, so I have problems in figuring the final layout.
How can I easily create the layout having more controls which share the same window area and are displayed one at a time ?
Setting A Design Time Only Data Context
Developing XAML in the Studio Designer can be greatly simplified by setting the Design-Time Data Context.
One implementation is based on setting a duplicate DataContext which will be ignored during the final compilation.
To implement the switching, add to the ViewModel, a property that will inform the designer whether it can be used in Development Mode or not.
I use an MVVMLight situation for this example, but for this declared instance property IsInDesignMode and static property ViewModelBase.IsInDesignModeStatic.
Example:
using System.ComponentModel;
namespace DataContextDesignTime.Example
{
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool _flag;
public bool Flag
{
get => _flag;
set
{
if (!Equals(_flag, value))
{
_flag = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Flag)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NotFlag)));
}
}
}
public bool NotFlag => !Flag;
}
}
<Window x:Class="DataContextDesignTime.Example.ExamleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataContextDesignTime.Example"
mc:Ignorable="d"
Title="ExamleWindow" Height="450" Width="800">
<d:Window.DataContext>
<local:MyViewModel Flag="True" NotFlag="True"/>
</d:Window.DataContext>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<StackPanel>
<Border Background="LightBlue" Height="200"
Visibility="{Binding Flag, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<Border Background="LightGreen" Height="400"
Visibility="{Binding NotFlag, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</Window>
In this example, you can change property values in XAML or in the Property Browser.
And you will immediately see the work of your bindings, triggers, how the display for certain data changes.
Note
This may fail on more complex VMs/packages, but in general by setting the DataContext at design time is not difficult.
I need to recompile the project to see the changes in the properties.
The XAML Designer panel has an «Enable/Disable Project Code» button.
, but during design phase in Visual Studio I see all of them, so I have problems in figuring the final layout.
This problem is easily resolved by bringing up the Document Outline tab in visual studio. Once open, navigate to the visible tree and toggle the eyeball to visibly hide/unhide the control[s] one is not interested in; during design time only.

XamlParseException using Extended.Wpf.Toolkit in VS extension project

I have an existing WPF application from which I'd like to make a VisualStudio extension.
Basically, I have a xaml window in which I use the library Extended.Wpf.Toolkit for AvalonDock. This application works perfectly without any issue.
I tried to re-use the same window in my extension project and I got XamlParseException on load
Here is the sample code which fails :
<Window x:Class="Company.VisualStudioExtension.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
Title="Window2" Height="300" Width="300">
<Grid>
<xcad:DockingManager AllowMixedOrientation="True" BorderThickness="1">
<xcad:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Test" />
</StackPanel>
</DataTemplate>
</xcad:DockingManager.DocumentHeaderTemplate>
<xcad:LayoutRoot x:Name="_layoutRoot">
<xcad:LayoutPanel Orientation="Horizontal">
<xcad:LayoutAnchorablePane DockWidth="300">
</xcad:LayoutAnchorablePane>
</xcad:LayoutPanel>
</xcad:LayoutRoot>
</xcad:DockingManager>
</Grid>
The exception is highlighted on the following line :
<xcad:LayoutPanel Orientation="Horizontal">
"The method or operation is not implemented."
EDIT
It seems registering all AvalonDock dll in GAC fixes the issue but obviously, it's not an acceptable solution...
I guess these dll are not properly registered while running as an Extension, I propably need to reference them in a specific way... for now, they are referenced in Extension's csproj + CopyLocal=True
EDIT2
Added source code to reproduce the issue https://github.com/MrLuje/VSPackage_NotWorking
There are 2 projects :
a WPF app with a working code in MainWindow
a VS Extension with non-working code in Window1 (in debug, you need to click in Tools > "My Command name")
I found an easier solution, 'ProvideBindingPath' this will add your current extension folder to the resolution folders of dlls.
[ProvideBindingPath]
public sealed class MainWindowPackage : Package
{
}
based on solution purposed in: VSIX - Cannot load file or assembly of a referenced dll
The solution of adding to the gac wont work 'as is'...VSIX extensions dont allow register on the gac, maybe a workaround will be run gacutil.
Followed #Will's answer and went with the following code which works fine :
protected override void Initialize()
{
base.Initialize();
InstallAvalonToGac();
}
private static void InstallAvalonToGac()
{
var dlls = new string[]
{
"Xceed.Wpf.AvalonDock.dll",
"Xceed.Wpf.DataGrid.dll",
"Xceed.Wpf.Toolkit.dll"
};
foreach (var dll in dlls)
{
var fullpath = Path.Combine(Environment.CurrentDirectory, dll);
new System.EnterpriseServices.Internal.Publish().GacInstall(fullpath);
}
}

How to add UserControl to a Panel on a WPF Window

I think I'm missing something that should be obvious here, but I'm drawing a blank on this one.
I've built a very primitive UserControl containing nothing more than a TextBox to use as a log window:
<UserControl x:Class="My.LoggerControl"
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"
x:Name="LoggerView">
<Grid x:Name="LayoutRoot">
<TextBox x:Name="LogWindow" AcceptsReturn="True"/>
</Grid>
</UserControl>
I don't expect that to be the best way to do it, but it should be good enough for a prototype.
The code-behind is similarly simple:
public partial class LoggerControl : UserControl, ILogger
{
public LoggerControl()
{
InitializeComponent();
}
private LogLevel level = LogLevel.Warning;
#region ILogger
public LogLevel Level
{
get { return level; }
set { level = value; }
}
public void OnError(string s)
{
if (level >= LogLevel.Error)
LogWindow.AppendText("ERROR:::" + s + "\n");
}
// ...
#endregion
}
The thing I can't figure out is how to add this control to my MainWindow.xaml. Simplifying, lets say my window looks like this:
<Window x:Class="My.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:My"
Title="Test" Height="350" Width="525">
<Grid>
<local:LoggerControl x:Name="LogView" />
</Grid>
</Window>
Even with something so simple, the Designer in Visual Studio 2010 can't load the main window. The error given is:
A value of type 'LoggerControl' cannot be added to a collectionor dictionary of type 'UIElementCollection'.
This error message has only one unrelated hit in the major search engines (plus duplicates) so I haven't found any useful help. Microsoft's own documentation seems to imply that this should work.
Any idea how to solve this?
<UserControl x:Class="My.LoggerControl"
xmlns:local="clr-namespace:My.LogTest"
Looks like you may have made a mistake in the namespacing? LoggerControl is listed as being the namespace My, while you're importing My.LogTest and assigning it to the xml-prefix local. Change this to:
xmlns:local="clr-namespace:My"
And I think it should work. Otherwise, fix the LoggerControl declaration.

What makes visual studio's designer kick in for design time support

I have a c# control library which contains my models, viewmodels and views. I hook everything up as I usually do but I do not get any design time feedback from visual studio's designer (blendability).
When I load my assambly in a WPF project and include the view as custom user control I'll get my design time feedback. Unfortunately this WPF Project is only a test shell because the view will live in another app.
It would be more efficient for my dev pipeline if I could have blendability (design time) support in my class library? What makes visual studio kick in to show my design time datacontext?
I even use d:DataContext="{d:DesignInstance dd:DesignViewModel}" in my class library. No design time data in class library.
Try
d:DataContext="{d:DesignInstance dd:DesignViewModel, IsDesignTimeCreatable=True}
There is a blog here that may help you too.
I found it really frustrating having to create either an empty constructor for my viewmodels, or to make derived classes all the time, just to please the WPF designer.
One solution that works for me (tested only with Visual Studio 2013) is using a static property to expose an instance of a design-time view model, for example
C# code
namespace WpfApplication2
{
public class Person
{
public Person(string id)
{
Id = id;
}
public string Id { get; private set; }
}
public static class DesignViewModels
{
public static Person Person
{
get { return new Person("Design time person id"); }
}
}
}
and the XAML
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:my="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<d:DesignProperties.DataContext>
<x:Static Member="my:DesignViewModels.Person" />
</d:DesignProperties.DataContext>
<TextBlock Text="{Binding Id}"/>
</Window>

Designer rejecting DataTemplate.DataType

I am try to fit some WPF into my current Windows Forms application. When I use this simple user control, the designer for that control does not reload.
This only happens in this application. If I make a clean Windows Forms project, add these files, the designer works fine.
I have tried a reload of Visual Studio, and cleans / rebuilds of the application.
Any ideas? (These are for the items in a ListBox, so x:Key is not an option.)
P.S. How do I get rid of all those trailing blank lines in my code listing?
DETAILS:
MyClasses.cs
namespace MyNamespace {
internal class MyClassInternal {}
public class MyClassPublic {}
}
MyUserControl.xaml
<UserControl x:Class="MyNamespace.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace"
Height="300" Width="300">
<UserControl.Resources>
<DataTemplate DataType="{x:Type local:MyClassInternal}"/> <!--OK-->
<ObjectDataProvider x:Key="ClassPublicKey" ObjectType="{x:Type local:MyClassPublic}"/> <!--OK-->
<!-- Type reference cannot find public type named 'MyClassPublic' -->
<DataTemplate DataType="{x:Type local:MyClassPublic}"/> <!--FAILS-->
</UserControl.Resources>
<TextBlock>Hello World</TextBlock>
</UserControl>
MyUserControl.xaml.cs
using System.Windows.Controls;
namespace MyNamespace {
public partial class MyUserControl :UserControl {
public MyUserControl() {
InitializeComponent();
}
}
}
It was caused by having a space in the Assembly name.

Resources