locked
DataForm does not display content RRS feed

  • Question

  • My DataForm is not displaying the content in hte ItemsSource collection.  Cna some one give me a hint as what I am doing wrong please?  This is my DataForm:

    <toolkit:DataForm  x:Name="dfCustomer"
                       ItemsSource="{Binding List}"
                       AutoGenerateFields="True"
                       CommandButtonsVisibility="navigation"/>

    This is my view model:

        public class CustomerViewModel: INotifyPropertyChanged
        {
            private ObservableCollection<Customer> list = new ObservableCollection<Customer>();
            private CustomerDomainContext context;

            public CustomerViewModel()
            {
                context = new CustomerDomainContext();           
                context.Load<Customer>(context.GetCustomersQuery(), loadOp =>
                {
                    foreach (var customer in context.Customers)
                    {
                        list.Add(customer);
                        NotifyPropertyChanged("itemAdded");
                    }
                }, null);
            }

            public ObservableCollection<Customer> List
            {
                get { return this.list; }
            }
           
            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }
        }

    The code behing Home.xaml is doing the following:

            private CustomerViewModel customerViewModel = new CustomerViewModel();
            public Home()
            {
                InitializeComponent();            
                Loaded += new System.Windows.RoutedEventHandler(Home_Loaded);
            }

            void Home_Loaded(object sender, System.Windows.RoutedEventArgs e)
            {
                dfCustomer.DataContext = customerViewModel;           
            }

    This is not working.  I can see that the navigation buttons are not active at startup and once the data has been loaded the buttons become enabled but nothing is displayed in the form.  If I click the navigation buttons then the current item is displayed.

    Can someone put me in the right direction here please?

     

     

    Thursday, August 26, 2010 4:32 AM

Answers

  • Hi,

    Please use a PagedCollectionView instead of ObservableCollection, on loaded delegate, call PagedCollectionView.MoveCurrentToFirst().

    Here is some code:

    MainPage.Xaml:

    <UserControl x:Class="Forum198118.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
    
        <Grid x:Name="LayoutRoot" Background="White">
            <toolkit:DataForm Height="100" HorizontalAlignment="Left" Margin="142,150,0,0" Name="dataForm1" VerticalAlignment="Top" Width="200" ItemsSource="{Binding List}" AutoGenerateFields="True" CommandButtonsVisibility="navigation" />
        </Grid>
    </UserControl>

    MainPage.cs
     

    public partial class MainPage : UserControl,INotifyPropertyChanged
    {
        private ObservableCollection<Course> list = new ObservableCollection<Course>();
        private DomainService1 client;
    
        public MainPage()
        {
            InitializeComponent();
            client = new DomainService1();
            client.Load<Course>(client.GetCoursesQuery(), loadop => {
    
    
                foreach (var course in client.Courses)
                {
                    list.Add(course);
                }
                List.MoveCurrentToFirst();
                NotifyPropertyChanged("List");
                
            }, null);
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }
    
        public PagedCollectionView List
        {
            get
            {
                return new PagedCollectionView(list);
            }
        }
    
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            dataForm1.DataContext = this;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    By the way, you should pass property name to NotifyPropertyChanged method.

    Monday, August 30, 2010 2:56 AM

All replies

  • For some reason the Observer - Observable pattern is not working in this case and I do not know if this is a bug, by design or I am doing something weird.  To "resolve" my problem I derived a DataForm which implements my version of IObserver

        public class ObserverDataForm: DataForm, IObserver
        {

            #region IObserver Members

            public void Notify(object anObject)
            {
                ItemsSource = anObject as ObservableCollection<Customer>;
            }

            #endregion
        }

    Now the CustomerViewModel becomes IObservable by implementing my own version of the interface.

        public class CustomerViewModel : INotifyPropertyChanged, IObservable
        {               
            private ObservableCollection<Customer> list = new ObservableCollection<Customer>();
            private CustomerDomainContext context;
            private Dictionary<IObserver, IObserver> observerContainer = new Dictionary<IObserver, IObserver>();

            public CustomerViewModel()
            {
                context = new CustomerDomainContext();           
                context.Load<Customer>(context.GetCustomersQuery(), loadOp =>
                {
                    foreach (var customer in context.Customers)
                    {
                        list.Add(customer);
                        NotifyPropertyChanged("itemAdded");
                        NotifyObservers(List);
                    }
                }, null);
            }

            public ObservableCollection<Customer> List
            {
                get { return this.list; }
            }

            #region Notify Property Changed
            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }
            #endregion

            #region IObservable Members

            public void Register(IObserver anObserver)
            {
                observerContainer.Add(anObserver, anObserver);
            }

            public void UnRegister(IObserver anObserver)
            {
                observerContainer.Remove(anObserver);
            }

            #endregion

           
            public void NotifyObservers(object anObject)
            {           
                foreach (IObserver anObserver in observerContainer.Keys)
                {
                    anObserver.Notify(anObject);
                }
            }
        }

    The code behind now sets the DataContext of this new DataForm and registers with the Observable:

     

          odfCustomer.DataContext = customerViewModel;

          customerViewModel.Register(odfCustomer);

     

    Now the data form loads fine, but I am not happy with this because it is too strange...  my rule of thumb is:  if it is too strange then it is probably wrong.

    Can someone comment please? 

    Friday, August 27, 2010 3:21 AM
  • Hi,

    Please use a PagedCollectionView instead of ObservableCollection, on loaded delegate, call PagedCollectionView.MoveCurrentToFirst().

    Here is some code:

    MainPage.Xaml:

    <UserControl x:Class="Forum198118.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
    
        <Grid x:Name="LayoutRoot" Background="White">
            <toolkit:DataForm Height="100" HorizontalAlignment="Left" Margin="142,150,0,0" Name="dataForm1" VerticalAlignment="Top" Width="200" ItemsSource="{Binding List}" AutoGenerateFields="True" CommandButtonsVisibility="navigation" />
        </Grid>
    </UserControl>

    MainPage.cs
     

    public partial class MainPage : UserControl,INotifyPropertyChanged
    {
        private ObservableCollection<Course> list = new ObservableCollection<Course>();
        private DomainService1 client;
    
        public MainPage()
        {
            InitializeComponent();
            client = new DomainService1();
            client.Load<Course>(client.GetCoursesQuery(), loadop => {
    
    
                foreach (var course in client.Courses)
                {
                    list.Add(course);
                }
                List.MoveCurrentToFirst();
                NotifyPropertyChanged("List");
                
            }, null);
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }
    
        public PagedCollectionView List
        {
            get
            {
                return new PagedCollectionView(list);
            }
        }
    
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            dataForm1.DataContext = this;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    By the way, you should pass property name to NotifyPropertyChanged method.

    Monday, August 30, 2010 2:56 AM
  • Thank you Frank!  Returning the PagedCollectionView instead of the ObservableCollection was the correct solution.  Thanks for caching my bug in the property name as well!

    Cheers!@ 

    Monday, August 30, 2010 4:40 PM