First off, of course I'm aware that this is one of the most repetitive questions to ask about... i'll save you a moment by saying that this has a twist.
First, the setup
<UserControl {d:DesignInstance Type=MyControl, IsDesignTimeCreatable=True}>
<Grid x:Name="root">
<FrameElement x:Name="ContextProxy" Visibility="Collapsed" />
...
<DataGridTextColumn.Visibility>
<!-- squiggly line on the SOURCE part -->
<Binding Source="{x:Reference Name=ContextProxy}"
Path=DataContext.IncludeThisColumn
/>
</DataGridTextColumn.Visibility>
</Grid>
</UserControl>
codebehind
public partial class MyControl {
// viewmodel for INPC (data lookups, child controls, etc)
public ViewModels.vmMyControl { get; } = new ViewModels.vmMyControl();
MyControl() { // ctor
this.root.DataContext = this; // to support DependencyProperty
}
// several dependency properties for external use/bindings
public static DP IncludeThisColumnDP = DP.Register(..., OnIncludeThisColumnChanged)
public bool IncludeThisColumn { GetValue(DP); } { SetValue(DP, value); }
// relay DP changes from parent / outside world, to internal ViewModel
private void OnIncludeThisColumnChanged(..)
{ (o as vmMyControl).ViewModel.IncludeThisColumn = e.NewValue; }
}
viewmodel
public class vmMyControl {
private readonly myObservableINPC<bool> _IncludeThisColumn;
public bool IncludeThisColumn { get/set for _IncludeThisColumn.Value }
public vmMyControl() { // ctor
// initialize INPC crap
this.IncludeThisColumn = new blah(nameof(IncludeThisColumn));
// data for designer
if (...GetIsInDesignMode)
Data_LoadMock();
}
public Data_LoadMock() {
// populate some of the data points
}
}
so generally speaking, I think I'm following best practices (other than mixing of DP/INPC, but it addresses my needs well, so whatever)...
user control's data context is applied to an internal root element (the top-level Grid)
Data context set to instance of usercontrol to enable DP.
user control instance has readonly property initialized to ViewModel
viewmodel uses GetIsInDesignMode to ensure data doesn't load (and actually, the code's DAL proxies also check an internal bool for indicating when they're being run as a unit test, to further confirm that they're disabled, with InternalsVisibleTo(UnitTestProject))
since datagrid column visibility can't be bound directly (not in the element tree or whatever), I added a FrameworkElement to act as a proxy to datacontext
The twist
So, first let me say that at runtime, the code works. All of the bindings, data loads, etc. No exceptions. This is purely a design-time issue, but it bugs me.
Since I'm aware of the null reference issues when dealing w/ WPF design mode, my first action when I saw the issue was to add:
MyControlTests.cs
[TestMethod]
public void InstantiateVM() {
Action a = () => { return new vmMyControl(); }
a.ShouldNotThrow(); // FluentAssertions
}
[TestMethod]
public void InstantiateUC() {
Action a = () => { return new MyControl(); }
a.ShouldNotThrow(); // FluentAssertions
}
here's the thing... both of the tests run successfully... and upon inspection (debug + breakpoint), no properties in the object result in an exception.
Environment
App is using framework 4.5 and C#6 (since i'm on VS2015)
I saw someone post about VS2015 hovering over the message to get more info, but it doesn't seem to do anything for me.
For what it's worth, I'm using VS2015 REL... was tempted to apply update 2 or 3, but there seem to be a few bugs here and there from what I'm hearing/reading.