none
Why doesn't the code get generated in our code-behind? RRS feed

  • Question

  • We're trying to learn how to use the drag-and-drop with entity framework (we're working with VS 2010, .NET 4).  I was directed to the video by Julie Lerman ( http://msdn.microsoft.com/en-us/data/gg638943.aspx ) which is excellent, but we're running into some issues trying to do the same thing.  I spent time writing up a DLL project where I put all of the EF models and so on, which run against a SQL Server Express database on the user's machine.  I know that Julie said that if she's working on a regular app, not a simple app or a demo app, she will use a separate project for the EF models/code/etc, so I believe what I've done is very similar, if not identical.

    Anyway, getting back to our problem.  In the video Julie copies the Customers object to a listbox onto the WPF window.  It generates the XAML.  Ours does the same thing.  But what we're not seeing is the code in the code behind, like what Julie shows in her video.  5:26 into the video she gets to the code behind, you can see a method generated there named GetCustomersQuery().  Then within the Window_Loaded event you can see code autogenerated with lines like:

    CustomersWPF.CustomersEntities customersEntities = new CustomersWPF.CustomersEntities();
    // etc...

    In our data, within the EF model, we have a table called ClientInformation, and that table has columns like FirstName and LastName.  We copied the LastName column from the EF data source onto the window, it created a textbox (which is appropriate for what we're trying to do here), but there's nothing at all in the code behind.  What have we done wrong?  Is it because it is a DLL project, which we've just set a reference to within the main WPF project?  Did we forget to set some sort of reference?  Did we forget some using statement?  Is there something I have to do within the DLL project to make it possible for the autogenerated code to appear in the code behind?  How do we make our DLL project work the way it does in Julie's video? 

    Rod

    Tuesday, October 2, 2012 1:49 PM

Answers

  • Hi mark n,

    I've had another problem come up which has pulled me away from this, but now I've been able to get back to it.  Based on another video by Julie Lerman which is here, I've concluded that you have to put some code into the code-behind, or view-model, to fetch the data.  I grant you that Julie's example is using a console app as the consuming project of the EF project, but the principle is the same.  Also, as a reminder, this would be true if it is a separate project, or as I've done an EF DLL assembly which I referenced in my WPF project.  And actually the code that is generated, when you drag-and-drop the field from the data source onto the window/page does hint at the fact that you have to do some coding yourself.  For example, when I dragged some fields onto my window I got the following generated code:

    System.Windows.Data.CollectionViewSource clientInformationViewSource = 
    	((System.Windows.Data.CollectionViewSource)(this.FindResource("clientInformationViewSource")));
    // Load data by setting the CollectionViewSource.Source property:
    // clientInformationViewSource.Source = [generic data source]
    

    So in order to assign the CollectionViewSource (which is the Source property of the clientInformationViewSource above) used the relevant ObjectSet from the DLL, like this:

    clientInformationViewSource.Source = asiContext.ClientInformations.Where(c => c.ClientNumber == 149092);

    This then worked fine.

    Rod

    • Proposed as answer by Alexander Sun Wednesday, October 10, 2012 9:13 AM
    • Marked as answer by Rod at Work Wednesday, October 10, 2012 3:07 PM
    Thursday, October 4, 2012 7:36 PM

All replies

  • Hello,

    I'm in the process of wrestling with WPF and EF and making them work nicely together...good luck, its a struggle.

    I've seen this video...is it the one where...

    a) she creates some data sources

    b) she drags them onto the WPF design surface.

    c) it creates loads of XAML for the control AND some static resources...AND...it should put something in your Window_Loaded event?

    Tuesday, October 2, 2012 3:05 PM
  • Yes, that is correct.  That is the very same video I'm referring to.

    Rod

    Tuesday, October 2, 2012 3:25 PM
  • And then there's a commented out line that says

                // Load data by setting the CollectionViewSource.Source property:
                // leafChannelMaster_EITServiceDetailViewSource.Source = [generic data source]

    ?

    so you delete the comment before the 2nd line and set your source.

    Which, ok, may be harder than it seems.

    you probably need to.

    create a new model (inside a using block)

    force it to load a base DBSet<T>

    and set the source to the base tables (DBSet<T>) local property.

    Tuesday, October 2, 2012 3:30 PM
  • Yes, but I wonder why the generated code doesn't include everything that the video has?  I'm starting over with a new project, added my entity framework DLL to the project, made the necessary modifications to the App.Config file.  Then I put a listbox onto the MainWindow and made a data source with just 1 table (the simplest), and dragged that on top of the listbox.  It generated some of the code behind, but not all of it.  Here's the XAML:

    <Window x:Class="WpfTest1.MainWindow"
    				xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    				xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    				Title="Test pulling data out of SQL Express" mc:Ignorable="d"
    				xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    				xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    				d:DesignHeight="447" d:DesignWidth="669" SizeToContent="WidthAndHeight" FontSize="15"
    				xmlns:my="clr-namespace:AsiEF;assembly=AsiEF" Loaded="Window_Loaded">
    	<Window.Resources>
    		<CollectionViewSource x:Key="clientInformationViewSource" d:DesignSource="{d:DesignInstance my:ClientInformation, CreateList=True}" />
    	</Window.Resources>
    	<Grid DataContext="{StaticResource clientInformationViewSource}">
    		<ListBox Height="325" HorizontalAlignment="Left" Margin="24,25,0,0" Name="listBox1"
    						 VerticalAlignment="Top" Width="295" DisplayMemberPath="City" ItemsSource="{Binding}" SelectedValuePath="City" />
    	</Grid>
    </Window>
    

    and here's the code behind:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using AsiEF;
    
    namespace WpfTest1
    {
    	/// <summary>
    	/// Interaction logic for MainWindow.xaml
    	/// </summary>
    	public partial class MainWindow : Window
    	{
    		public MainWindow()
    		{
    			InitializeComponent();
    		}
    
    		private void Window_Loaded(object sender, RoutedEventArgs e)
    		{
    
    			System.Windows.Data.CollectionViewSource clientInformationViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("clientInformationViewSource")));
    			// Load data by setting the CollectionViewSource.Source property:
    			// clientInformationViewSource.Source = [generic data source]
    		}
    	}
    }
    

    So, why don't I have an auto-generated GetCityQuery() (or GetCitiesQuery() ), and more code in the Window_Loaded event?

    Rod

    Tuesday, October 2, 2012 3:57 PM
  • Then I put a listbox onto the MainWindow and made a data source with just 1 table (the simplest), and dragged that on top of the listbox

    "Our survey said?" (this may not translate?)

    EuuuuuuErrrrrrr. (do you get "family fortunes"?)

    this is exactly what I did, for the 1st 10 times I tried to get this blasted thing to work....pulled my hair out....googled...pulled my hair out.

    Dont put the listbox on the window.

    Dont drag the datasource to the control.

    There is a little drop down list next to the datasource, where you select what sort of control you want to CREATE when you drag and drop the datasource onto the design window....in an empty space

    Then it will CREATE a NEW control and fill in some of the XAML for things like columns for you.

    Its not you, its it....I think they found this easier to implement, but it's slightly counter intuitive....drag drop creates controls....it doesnt operate on existing controls.

    Tuesday, October 2, 2012 4:13 PM
  • ooo,

    I've answered the wrong question!....I told you the answer to my problem!....

    ummmm

    you don't get more data in the Window_Loaded event, because it doesn't know what to put there.

    the only line your missing is what the source is.

    But what did you create as your datasource?

    Tuesday, October 2, 2012 4:18 PM
  • using (var model = new ModelContainer)
    {
       model.Foo.Load();
       clientInformation.Source = model.Foo.Local;
    }

    ?

    depends where your code's coming from.

    Tuesday, October 2, 2012 4:21 PM
  • I made 1 small error.  I hadn't included the System.Data.Entity assembly.  However, I distributed the EntityFramework.dll with my .dll, so I thought that would be sufficient.  Ultimately that didn't solve my problem.

    In your code you're using a variable 'model'.  I'm not sure what that is supposed to be.  Are you using MVVM, and therefore the 'model' is a representation of your data in the MVVM pattern?

    In my EF .dll, my main namespace is AsiEF.  The System.Data.Objects.ObjectContext I called ASIEntities.  I've changed the Window_Loaded event to this:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
    
    	System.Windows.Data.CollectionViewSource clientInformationViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("clientInformationViewSource")));
    	// Load data by setting the CollectionViewSource.Source property:
    	// clientInformationViewSource.Source = [generic data source]
    
    	using (AsiEF.ASIEntities context = new ASIEntities())
    	{
    		clientInformationViewSource.Source = context.ClientInformations.Where(c => c.City != "");
    	}
    }
    

    OK, so this works and all.  But it still is not what we wanted.  We really want drag-and-drop to work without having to do any, or much, coding. I know that in the video Julie talked about needing to create data sources, I think by hand, if she used a separate project for EF.  I guess I'm back to asking, is putting the EF logic/models in a separate DLL project what's preventing all of that cool code generation from not being done?

    Rod

    Tuesday, October 2, 2012 5:13 PM
  • mark n, I had a second thought which may relate to what I'm struggling with.  Perhaps there's some attributes which I need to apply to the methods of the classes I have in my EF model.  So that, for example, the GetCustomersQuery() method in the video is autogenerated when we drag-and--drop a data source in the VS 2010 designer.  Might I be missing an attribute somewhere?


    Rod

    Tuesday, October 2, 2012 6:41 PM
  • Hi mark n,

    I've had another problem come up which has pulled me away from this, but now I've been able to get back to it.  Based on another video by Julie Lerman which is here, I've concluded that you have to put some code into the code-behind, or view-model, to fetch the data.  I grant you that Julie's example is using a console app as the consuming project of the EF project, but the principle is the same.  Also, as a reminder, this would be true if it is a separate project, or as I've done an EF DLL assembly which I referenced in my WPF project.  And actually the code that is generated, when you drag-and-drop the field from the data source onto the window/page does hint at the fact that you have to do some coding yourself.  For example, when I dragged some fields onto my window I got the following generated code:

    System.Windows.Data.CollectionViewSource clientInformationViewSource = 
    	((System.Windows.Data.CollectionViewSource)(this.FindResource("clientInformationViewSource")));
    // Load data by setting the CollectionViewSource.Source property:
    // clientInformationViewSource.Source = [generic data source]
    

    So in order to assign the CollectionViewSource (which is the Source property of the clientInformationViewSource above) used the relevant ObjectSet from the DLL, like this:

    clientInformationViewSource.Source = asiContext.ClientInformations.Where(c => c.ClientNumber == 149092);

    This then worked fine.

    Rod

    • Proposed as answer by Alexander Sun Wednesday, October 10, 2012 9:13 AM
    • Marked as answer by Rod at Work Wednesday, October 10, 2012 3:07 PM
    Thursday, October 4, 2012 7:36 PM
  • sorry I got pulled away by different problems.

    I'm not sure I'm the right person to talk to as I'm largely stuggling with the same problems now, rather than having had them 2 years ago, and now understand how this all works.

    I personlly found this blog and example the most informative yet...(the example more than the blog).

    http://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/

    I wanted...

    to use EF 5

    not have to hand struggle my way through XAML (because the nuances of binding etc are still difficult for me to do....and the whole thing is not typesafe, so the compiler rarely tells you where the problems are....anyone who claims that "Views" do not need to be tested are mad...)

    So I want to drag drop data sources onto the design page and largely get 50% of the code "for free" (the trick here is to NOT put a control on the form, but to drag the data source directly onto the design surface (with the correct drop down selected next to the source)).

    Direcly bind to EF sources...not constantly copy stuff in and out of Lists

    So....at the moment....I'm following the example given above, but manually editing the ItemSource/DataContexts in the XAML to bind to the ObservableCollection<T>s exposed by my VM class relative to the datacontext of the XAML window.

    And then setting the DataContext of the Window in the constuctor to be the VM (as per sample code in the link)

    so my model is the EF model

    my VM looks like the one in the example

    my window code looks like....almost no code!

        public partial class MainWindow : Window
        {
            LeafChannelMaster_EITServiceDetail mvvm;
            public MainWindow()
            {
                InitializeComponent();
                this.mvvm = new LeafChannelMaster_EITServiceDetail();
                this.DataContext = mvvm;
            }
            private void Button_Click_2(object sender, RoutedEventArgs e)
            {
                this.mvvm.SaveChanges();
            }
            protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
            {
                base.OnClosing(e);
            }
        }

    and my data grids in my XAML look like

    <DataGrid x:Name="eitServicesDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding EitServices}" Margin="212,31,-95,-109" Grid.Row="5" Grid.RowSpan="3" RowDetailsVisibilityMode="VisibleWhenSelected">

    where "EitServices" is the name of the ObservableCollection<T> property in my VM class.

    70% of my columns were autogenerated using drag drop, and the other 30% were created using the property window to add drop down boxes etc anc bind to other ObservableCollection<T> exposed by my VM class....

    Friday, October 5, 2012 10:35 AM
  • Thank you, mark n, for the link.  Interesting blog post.

    Rod

    Friday, October 5, 2012 3:29 PM
  • Hi Rod,

    Is your problem solved? If you have anything unclear, please feel free to let us know.

    Good day.


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us

    Monday, October 8, 2012 1:56 AM
  • Hi Alexander

    I think, for the most part, my question has been answered.  It appears to me that when you put the EF code into a separate project, or a class library and compile that into a DLL which you then reference in another project, then extensive code-behind code doesn't get generated.  A basic template does, which I listed back on October 4, but that's all.  In Julie Lerman's video, when she put the EF code into the same project as the rest of her code (in the video I saw it was in with the WPF code), then more extensive code generation seemed to occur.  e.g.: there was a GetCustomers() method that seems to have been generated automatically (not sure if that's the correct name of the method or not).  But I'm wondering if that GetCustomers() method wasn't something that she put there previously, in some other video, before the video I saw on WPF.  And WPF is what I'm focusing upon now.

    Here's the bottom line: if it is the case that placing the EF code in the same project as the rest of one's code, does give you lots more generated code behind, besides the creation of a CollectionViewSource object, then it would be nice if that same code is also generated when one puts the EF code in a separate project or DLL.  Sort of like where one could decorate the methods with attributes that one wants to have automatically generated or stubbed out in the other project's code.  I'm thinking of WCF interfaces which have attributes decorating method declarations, data types, etc.  That's really handy, and I think the same thing could be done with EF.


    Rod

    Tuesday, October 9, 2012 4:51 PM
  • Hi Rod,

    I think it maybe is an issue. Could you please create an issue on this site: http://entityframework.codeplex.com/workitem/list/basic

    Have a nice day.


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, October 10, 2012 9:17 AM