1

I am getting an issue that I have seen posted before but the answers seem only applicable to ASP.NET MVC, whereas I am using WPF (with Entity Framework).

My XAML designer in VS currently looks like this:

enter image description here

This is on a UserControl where the code is very simple:

<UserControl x:Class="door_system.Views.HomeView"
                 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"
                 xmlns:viewModels="clr-namespace:door_system.ViewModels"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.DataContext>
        <viewModels:HomeViewModel/>
    </UserControl.DataContext>

    <Grid>
        <DataGrid AutoGenerateColumns="False">
            <DataGridTextColumn Width="*"/>
            <DataGridTextColumn Width="*"/>
            <DataGridTextColumn Width="*"/>
        </DataGrid>
    </Grid>
</UserControl>

So my project setup looks like so:

enter image description here

There is only one app.config file that definitely contains the connection string:

<connectionStrings>
  <add name="MicrotrakContext" connectionString="metadata=res://*/Models.MicrotrakModel.csdl|res://*/Models.MicrotrakModel.ssdl|res://*/Models.MicrotrakModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=*******;initial catalog=MicrotrakEvolution;user id=******;password=********;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

When I build the project there are no errors. When I run the project it performs without error too. Is this a bug I have discovered?

Aside from name changes I have two other projects that are setup in almost exactly the same way, both build and run without issue.

The Task calling the Context in HomeViewModel:

private Task LoadTransactionsTask()
{
    return Task.Run(() =>
    {
        using (var context = new MicrotrakContext())
        {
            AllTransactions = new ObservableCollection<Transaction>(
                (from record in context.Transactions
                    select record)
                .Where(x => x.CreationTime >= DateTime.Today)
                .ToList());
        }
    });
}
CBreeze
  • 2,925
  • 4
  • 38
  • 93
  • Where's the *code* and the actual exception? Have you tried debugging your code? XAML doesn't query databases. How do you define and use your EF context? – Panagiotis Kanavos Sep 21 '17 at 12:50
  • @PanagiotisKanavos Please see the edit. – CBreeze Sep 21 '17 at 12:54
  • What does the *stack trace* show? And please, please, please, ***PLEASE*** post the connection string text, not an indivible black screenshot of the connection string text. That looks like a blurred EF connection string. The element doesn't look like a blurred *EF config* section. – Panagiotis Kanavos Sep 21 '17 at 12:54
  • "My designer in VS currently looks like this" Are you referring to your XAML designer, EF Model designer or something else? – Canica Sep 21 '17 at 12:55
  • @jcruz XAML designer. – CBreeze Sep 21 '17 at 12:57
  • This is what I use for my view model `d:DataContext="{d:DesignInstance Type=vm:MainViewModel, IsDesignTimeCreatable=True}"` you will need to tweak it to your needs though. – XAMlMAX Sep 21 '17 at 13:11
  • @XAMlMAX It's strange that I would need to do that because as I said I have other projects the same as this one, without using `d:DataContext` that have no issues – CBreeze Sep 21 '17 at 13:12
  • It will, if the UserControl is in another assembly. Say you main window is in `.exe` and this UC would be in `.dll` then it will not have access to the config file. – XAMlMAX Sep 21 '17 at 13:14
  • @XAMlMAX How can I check which assembly each is in? – CBreeze Sep 21 '17 at 13:16
  • It will be down to your solution. Only you can know where your UserControl is. – XAMlMAX Sep 21 '17 at 13:18
  • @XAMlMAX from the image of my project setup above I just cannot see how they can be anywhere different from each other.... – CBreeze Sep 21 '17 at 13:42
  • I can't view images as I am at work and here we use proxy for internet access. – XAMlMAX Sep 21 '17 at 13:47
  • @XAMlMAX I am using `d:DataContext` now and same issue. – CBreeze Sep 21 '17 at 14:29

3 Answers3

2

Why the VS Designer throws exception

Some of your application code (e.g. HomeViewModel) is executed by the XAML designer process. Your code (e.g. new MicrotrakContext()) looks for configuration file of the current process, not your app.config.

How to fix it

You should prevent your application to access database, file system or any other I/O operations and provide some design time data instead.

I've described some techniques here: Daniel Turan's answer to: Does mmvm stop the ability for Visual Studio designer to show XAML

Basically, you can check in your code:

if (DesignerProperties.GetIsInDesignMode(someDepenencyObject))
{
    LoadDesignTimeData();
}
else
{
    LoadRealData();
}

EDIT:
my prefered way is DesignTime viewmodel:

public class HomeViewModelDesignTime : HomeViewModel
{
    protected override Task LoadTransactionsTask()
    {
       //load some hard coded design time data
    }
}

tell the designer to use this class:

<UserControl x:Class="door_system.Views.HomeView"
    d:DataContext="{d:DesignInstance Type=local:HomeViewModelDesignTime, IsDesignTimeCreatable=true}"

you can than instatiate you real ViewModel in codebehind for example.

TIP: create your own Project Item Template in Visual Studio, that will create UserControl with ViewModel and DesignTimeViewModel for you, so you don't have do it manually each time.

Liero
  • 25,216
  • 29
  • 151
  • 297
  • From the XAML code I have in the question above I can't see that I am doing any operations like that? That is all the XAML code I have above. Why would the code of the designer be looking for the config file? – CBreeze Sep 22 '17 at 07:15
  • because you are instantiating your `HomeViewModel` in xaml, and it is acessing database by entity framework. I guess you call `LoadTransactionsTask` from HomeViewModel's ctor – Liero Sep 22 '17 at 07:24
  • Thanks for your time. Should I instead instantiate my `ViewModel` in codebehind rather than XAML? – CBreeze Sep 22 '17 at 07:59
  • XAML should definitelly have information about ViewModel's type. You can do it either by instantiating ViewModel in xaml, just like you did, or alternatively using `{d:DesignInstance}` markup extension. See my edit and the link provided in my answer. – Liero Sep 22 '17 at 08:24
  • Update - even with your edit I am still getting a message saying it cant find the connection string, however now it is in the XAML code itself and I can see the designer. – CBreeze Sep 22 '17 at 13:38
  • Its because you are still calling db somewhere. You can debug xaml designer, it will show you where the exception is thrown. Google debugging xaml designer – Liero Sep 22 '17 at 15:55
0

Is you code compiling properly at this point: using (var context = new MicrotrakContext()) <-- Does it know what MicrotrakContext() is?

You can do a quick search for: : base("name= the expectation would be MicrotrakContext will be the value following name=.

David
  • 93
  • 1
  • 7
0

I had the same problem. This happens because you are trying to do some database access in design time. To solve this problem:

  1. Remove all the code from the User Control constructor (just let there the InicializeComponent method); The removed code, should be inserted in the userControl_Load method;
  2. Just verify if it is in design mode before executing the methods that have queries.

    if (!DesignMode)
    {
      // Functions that have any database access should be here (eg. queries, inserts, etc)
    }