4

Hi I'm fairly new to WPF and C#, so please be easy on me if this is just a silly question:

I'm using VS2012, Entity Framework to create a model of a pre-exisiting database and I would like to bind some tables to some ListView... Now, I know there are different ways to do that but when I try to use an ObjectDataProvider I get an error at design time "No connection string named ... could be found in the application config file".

The strange thing is that if I run my application everything is working as it should, I just would like to remove that ugly error message and hopefully to get data in my list ad design time (that's why I would like to use an objectdataprovider).

Here are some parts of my code:

App.Config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="BibliotecaEntities" 
         connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string='data source=(LocalDB)\v11.0;attachdbfilename=&quot;G:\PROGETTI-SOFTWARE\c# tests\Biblioteca\Biblioteca\biblioteca-db.mdf&quot;;initial catalog=BibliotecaDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework'" 
         providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

ListaScaffali.xaml:

<Window x:Class="Biblioteca.ShelvesList"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Biblioteca;assembly=" 
        Title="ShelvesList" Height="341" Width="609">

    <Window.Resources>
        <ObjectDataProvider ObjectType="{x:Type local:BooksDB_Handler}" MethodName="TuttiGliScaffali" x:Key="ScaffaliObjSrc" />
    </Window.Resources>

    <Grid>
        <Grid>
            <ListView Name="listaScaffali" ItemsSource="{Binding Source={StaticResource ScaffaliObjSrc}}">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Scaffali Disponibili:" DisplayMemberBinding="{Binding Scaffale}" />
                    </GridView>
                </ListView.View>
            </ListView>
        </Grid>
    </Grid>
</Window>

BooksDB-Handler.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Data.Entity;
using System.Collections.ObjectModel;

namespace Biblioteca
{
    public static class BooksDB_Handler
    {

    ...

        public static ObservableCollection<Scaffali> TuttiGliScaffali()
        {
            using (var ctx = new BibliotecaEntities())
            {

                var reader = from d in ctx.Scaffali
                             select d;
                return new ObservableCollection<Scaffali>(reader);
            }
        }

    ...

    }
}

In my DB the Table "Scaffali" has only two columns: "ScaffaliID" (identity) and "Scaffale".

I read somewhere that this could be a Visual Studio bug and tried various things:

  1. rebuild several times
  2. avoid # in paths
  3. compile for 32bits (I'm running Win8 x64)

but till now had no luck...

Thanks for your kind answer.

-= UPDATE 04/03/2013 =-

So far I still haven't found what are the conditions causing this strange behaviour, anyway I found that if I just build (not rebuild) two times in sequence the error message just disappear and everything seems to work as it should...

Catullo
  • 61
  • 1
  • 4
  • ...when I'm writing code and the application is not running. Maybe I used the wrong words to describe that phase? – Catullo Feb 16 '13 at 16:05

3 Answers3

3

I had the same issue, and what I found out is that during design time, IDE does not seem to be reading the App.config to get the connection string so it blows up when establishing the connection. What I ended up doing is checking if code is in design time and manually creating a few of the items for design purposes.

I use the following code to find out if the environment is in design mode:

public static bool IsInDesignMode
{
    get
    {
        #if Silverlight
            return !HtmlPage.IsEnabled;;
        #else
            return DesignerProperties.GetIsInDesignMode(new DependencyObject());
        #endif
    }
}

Then in my code where I am returning the items I do the following:

if (IsInDesignMode)
{
    GetSampleData();
}
else
{
    GetQueryData();
}

And I simply implement those two methods.

There may be a better solution, but this worked well for me.

ZanderAdam
  • 434
  • 2
  • 13
  • 1
    Thanks for your suggestion, that seems an effective solution but also make things a little bit more complex. I'm tring to use ObjectDataProviders to speed up the design of the UI: adding code complexit to achive that for me, at this time, doesn't really help. It seems to me that this is a VisualStudio Bug, what I would really like is to find out which conditions are making it expose and see if I can avoid that. – Catullo Feb 16 '13 at 16:10
1

This solution looked promising, but I have yet to get it to work for me...

Source: http://developernote.com/2012/03/rich-design-time-experience-with-wpf-and-ef-in-visual-studio-2010/

Sometimes the ability to see the data at design time significantly facilitates the creation of WPF controls. If I am developing a WPF control with complex UI using data bound controls, I usually define a property for accessing some typical data item:

public static ComplexData DesignTimeItem
{
    get
    {
        using (DatabaseContext db = new DatabaseContext())
        {
            var products = from p in db.products.Include("ProductType")
                           where p.product_id == 131
                           select p;

            product product = products.First();

            return new ComplexData(product, "100 kg");
        }
    }
}

and then I use this property directly in XAML at design time:

<UserControl x:Class="SomeControl"
    ...
    xmlns:local="clr-namespace:ControlNamespace"
    DataContext="{Binding Source={x:Static local:ComplexData.DesignTimeItem}, Mode=OneWay}"
    ...
>

Then I need to do the final step. The problem is that the default entity context constructor (DatabaseContext) uses the connection string included in run time application configuration file app.config:

<connectionStrings>
  <add name="MyContext" connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=MySql.Data.MySqlClient;provider connection string=&quot;password=******;User Id=myuser;server=myserver;database=mydb;Persist Security Info=True;charset=utf8&quot;" providerName="System.Data.EntityClient"/>
</connectionStrings>

but at design time the application configuration file is devenv.exe.config which doesn’t include the connection string and so the creation of my WPF control fails causing the designer to fail to load. To solve this problem I simply copy the connection string included in app.config to devenv.exe.config located in "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\" and restart Visual Studio.

Greg Mulvihill
  • 1,665
  • 1
  • 15
  • 12
0

Have you tried to construct the DataContext object with ConnectionString yourself instead of letting the framework use the one specified in configuration file? I usually prefer to construct that object myself, so i can easily move it to another assembly and inject the connection dependency. But that is another story. In your case, i would recommend you try these things:

  1. Keep connection string in webconfig.
  2. Construct the context yourself

    var connectionStringBuilder = new EntityConnectionStringBuilder { Metadata = "{metadata}", Provider = "{provider}", ProviderConnectionString = "{connection string from config}" };

    var ctx = new BibliotecaEntities(connectionStringBuilder.ToString());

I just give a hint so you can try. I have not tried it with the full detail. Hope it helps.

Thai Anh Duc
  • 524
  • 6
  • 12
  • Yes, that's similar to what I use to do in more familiar environments... I'll try your suggestion, thanks. – Catullo Feb 16 '13 at 16:17