Powered by MSDN

US - English
NEW! Silverlight 5 is available Learn More

Add new entity via DataForm buttons RSS

13 replies

Last post Feb 08, 2010 09:04 PM by Casimodo72

(0)
  • TomBeeby

    TomBeeby

    Participant

    1161 Points

    188 Posts

    Add new entity via DataForm buttons

    Jul 16, 2009 07:08 AM | LINK

    This is going to be a longish post... what I am finding is if I bind a DataForm's ItemsSource to a DomainDataSource control's Data property, the DataForm shows me all the buttons I ask for in CommandButtonsVisibility (Add, Edit, Delete, etc) In other words, it works as expected (and just like all the demo code online)

    If I take the same DomainContext (but this time in a presenter of the view) and bind the ItemsSource of a DataForm to an EntityList<TEntity> that has been loaded via the context, the Add & Delete buttons of the DataForm remain grey (disabled), but the rest of the DataForm (edit, nav) works as expected.

    To start with, here is my ultra simplitic DomainService:

     

    [EnableClientAccess()]
    public class PersonService : DomainService
    {
    public IQueryable GetPerson()
    {
    return PersonHelper.GetList().AsQueryable();
    }

    [Insert]
    public void InsertPerson(Person p)
    {
    }

    [Update]
    public void UpdatePerson(Person p)
    {
    }

    [Delete]
    public void DeletePerson(Person p)
    {
    }
    }
      

    Here is the XAML of a page using the DomainDataService control. This WORKS AS EXPECTED (i.e. Navigation works, edit works, add works, delete works, commit works, cancel works)

     

    <StackPanel x:Name="ContentStackPanel">

    <ria:DomainDataSource x:Name="dds1" AutoLoad="True" QueryName="GetPersonQuery">
    <ria:DomainDataSource.DomainContext>
    <loc:PersonContext />
    </ria:DomainDataSource.DomainContext>
    </ria:DomainDataSource>

    <dataForm:DataForm AutoGenerateFields="True" AutoEdit="False" ItemsSource="{Binding Data, ElementName=dds1}"
    CommandButtonsVisibility="All" Header="Person Edit">
    </dataForm:DataForm>


    </StackPanel>

      

    Here's the other approach, using a presenter and a Domain Context. Firstly, the codebehind / presenter (very simplistic implementation):

     

    public partial class Home : Page
    {
    public Home()
    {
    InitializeComponent();
    DataContext = new HomePresenter();
    }

    // Executes when the user navigates to this page.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    }
    }

    public class HomePresenter : INotifyPropertyChanged
    {
    public PersonContext PersonContext { get; set; }
    public HomePresenter()
    {
    PersonContext = new PersonContext();
    PersonContext.Load(PersonContext.GetPersonQuery(), PersonsLoadedCallback, null);
    }

    private void PersonsLoadedCallback(LoadOperation op)
    {
    NotifyChange("PersonContext");
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyChange(string property)
    {
    if (PropertyChanged == null) return;
    PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
    }

      

    And here's the XAML:

     

    <StackPanel x:Name="ContentStackPanel">

    <dataForm:DataForm Header="Person Form" ItemsSource="{Binding PersonContext.Persons}" AutoGenerateFields="True"
    CommandButtonsVisibility="All" AutoEdit="False" >
    </dataForm:DataForm>

    </StackPanel>

      

    The second attempt displays the list of items in the DataForm and allows navigation, edit, commit, cancel. The Add & Delete buttons, however, remain disabled.

    This has been frustrating me all day, because the two techniques should surely yield the same results. In the second case, PersonContext.Persons is of type EntityList<Person> and the properties CanAdd, CanEdit, CanDelete are all true.

    Is this a BUG?! am i missing something? i like the idea of the DomainDataSource, but the app I am building uses MVP and data binding. We'd be breaking our pattern to make data access purely declarative

  • TomBeeby

    TomBeeby

    Participant

    1161 Points

    188 Posts

    Re: Add new entity via DataForm buttons

    Jul 16, 2009 07:31 AM | LINK

    After a bit more experimentation, I tried creating a DomainDataSource in the Presenter, like this:

     

    public partial class Home : Page
    {
        public Home()
        {
            InitializeComponent();
            DataContext = new HomePresenter();
        }
    
        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
    
    public class HomePresenter : INotifyPropertyChanged
    {
        public DomainDataSource PersonDDS { get; set; }
    
        public HomePresenter()
        {
            PersonDDS = new DomainDataSource();
            PersonDDS.DomainContext = new PersonContext();
            PersonDDS.QueryName = "GetPersonQuery";
            PersonDDS.Load();
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyChange(string property)
        {
            if (PropertyChanged == null) return;
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

      

    And made the the XAML look like this:

     

    <StackPanel x:Name="ContentStackPanel">
    
        <dataForm:DataForm Header="Person Form" ItemsSource="{Binding PersonDDS.Data}"  AutoGenerateFields="True" 
            CommandButtonsVisibility="All" AutoEdit="False" >
        </dataForm:DataForm>
    
    </StackPanel>

      

    Now - interestingly - this works as expected. the collection is bound to the dataform and all buttons are visible and work correctly.

    Is it good practice to use a DomainDataSource in the codebehind / presenter ? it certainly seems less flexible than using an instance of the DomainContext... interested to get some perspectives here

  • TomBeeby

    TomBeeby

    Participant

    1161 Points

    188 Posts

    Re: Add new entity via DataForm buttons

    Jul 16, 2009 08:22 AM | LINK

    To simplify things even further (remove the Presenter):

    Codebehind:

     

    public partial class Test : Page
    {
    public Test()
    {
    InitializeComponent();
    var ctxt = new PersonContext();
    dataform1.ItemsSource = ctxt.Persons;
    ctxt.Load(ctxt.GetPersonQuery());
    }

    // Executes when the user navigates to this page.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    }

    }

      

    XAML:

     

    <dataForm:DataForm x:Name="dataform1" AutoEdit="False" CommandButtonsVisibility="All" />

      

    Again, navigation and edit works, Add & Delete are disabled.

    This can't be the way it is supposed to work!

  • Maud

    Maud

    Contributor

    3551 Points

    483 Posts

    Re: Add new entity via DataForm buttons

    Jul 22, 2009 11:16 AM | LINK

    Hi,

    I'm not sure if dataform support add delete operation on DomainSource directly. dataform manipulate datasource as a IEnumable collection, but domainsource need a excute a group of operation to confirm the modification on entities.

    DomainDataSource like an adapter to cooperate with datapresenter (dataform/datagrid) and datasource (DomainSource).

    That's what I think.

    Maud
  • tadam

    tadam

    Member

    178 Points

    36 Posts

    Re: Re: Add new entity via DataForm buttons

    Jul 22, 2009 06:20 PM | LINK

    Tom - The reason the DataForm won't bind directly to Persons is that the DataForm uses a ICollectionView\IEditableCollectionView internally which looks at the interfaces the object\collection you are binding to implements.  If the object\collection implements IList and their is a parameter-less constructor for the type in the collection then Add's will be allowed.  The issue is that EntityList doesn't support IList.  As mentioned before you could use DDS.  If you didn't want to use DDS you could do something similar to what DDS does, basically add the items returned from the query into an IList and then when Add\Removes are done on that list you can call the subsequent Add\Remove on EntityList.  You would then pass the IList to DataForm and then it would work as you expect.

    tadam

    -- Please mark the post as answered if I've answered you question.
  • ColinBlair

    ColinBlair

    All-Star

    28559 Points

    4828 Posts

    Re: Re: Add new entity via DataForm buttons

    Jul 22, 2009 07:02 PM | LINK

    There is another thread  discussing some of these issues. The problem is that the collection that backs the DDS, EntityCollectionView, is internal to RIA Services. Jeff Handley is talking about create a version of EntityCollectionView which we can use directly and that will make it much easier to implement binding between the DataForm and {ViewModel, Presenter, TheBindeyThing}s.

  • JeffHandley

    JeffHandley

    Participant

    764 Points

    146 Posts

    Microsoft

    Re: Re: Add new entity via DataForm buttons

    Aug 14, 2009 09:57 AM | LINK

    I've put together a way to get around this problem of binding the DataForm directly to the EntityList.  I blogged about it here:

    http://jeffhandley.com/archive/2009/08/14/entitycollectionviewconverter.aspx


    You'll notice that I'm using the name EntityCollectionView for the solution, but please don't confuse this with the EntityCollectionView that Colin mentioned.  During a meeting today, we realized that EntityCollectionView is really poorly named for the DomainDataSource, and that name should really be used for something like what my blog post provides.  I knew there was a good reason the DDS EntityCollectionView eas internal. :-)

    Note: the solution I provided is only tested for blog quality - it works on my machine in the simple cases I've tested.  I'd love to hear how it works for you.

    Thanks,
    Jeff Handley

    DataForm EntityList

  • bobg2009

    bobg2009

    Member

    82 Points

    184 Posts

    Re: Re: Add new entity via DataForm buttons

    Jan 25, 2010 12:31 AM | LINK

     Hi Jeff,

    I am unable to get your code to work with the November release of WCF Ria Services. 

    Are you able to assist?

     

    cheers.

  • Casimodo72

    Casimodo72

    Participant

    1042 Points

    458 Posts

    Re: Re: Add new entity via DataForm buttons

    Jan 25, 2010 03:37 AM | LINK

    jeffhandley

    we realized that EntityCollectionView is really poorly named for the DomainDataSource

    A DDS is an EntityCollectionView - interesting.

    Can anyone elaborate on this?

    Regards,

    Kasimier

  • ColinBlair

    ColinBlair

    All-Star

    28559 Points

    4828 Posts

    Re: Re: Add new entity via DataForm buttons

    Jan 25, 2010 03:34 PM | LINK

    Casimodo72

    A DDS is an EntityCollectionView - interesting.

    Can anyone elaborate on this?

    There is an internal class inside WCF RIA Services named EntityCollectionView. It is used by the DDS to do the paging. At one point there was talk about making it public, instead they created the public DomainDataSourceView which interacts with the DDS and the EntityCollectionView.

    As a separate issue, there needs to be a public EntityCollectionView as well. If Jeff is successful getting the source code of RIA Services shipped then I am planning to release one as part of RIA Services Contrib.