Avatar billede bmdk Nybegynder
23. september 2009 - 20:13 Der er 2 kommentarer og
1 løsning

Hjælp til forståelse af Model View-ViewModel (silverlight)

Hey alle,

Jeg er i øjeblikket igang med, at prøve at forstå Model View-ViewModel mønsteret og har i den forbindelse lavet en lille test-applikation til det :)

Min arkitektur er rimelig simpel og lige efter bogen i øjeblikket.

- Client mappe
    - ViewModel class lib
    - Views (xaml pages)

- Server mappe
    - ASP.NET website til at hoste silverligt app
    - Model class lib

- Service mappe
    - Services class lib

Jeg har fundet ud af, at få et Customer objekt med op igennem lagene og kan hive informationer ud af det (f.eks. Firstname)

Der hvor jeg sidder fast i øjeblikket er, at hvis jeg får en hel liste tilbage af Customer objekter, hvordan får jeg så samtlige af disse "hevet ud" og listet i f.eks. en listbox?

Min nuværende CustomerViewModel.cs ser i øjeblikket sådan her ud:

    public class CustomerViewModel : INotifyPropertyChanged
    {
        private Customer _customer = null;

        public Customer Customer
        {
            get { return _customer; }
            set
            {
                this._customer = value;
                RaisePropertyChanged("Customer");
                RaisePropertyChanged("AllCustomers");
            }
        }

        public void GetCustomers()
        {
            CustomerServiceClient client = new CustomerServiceClient();
            client.GetCustomersCompleted += new EventHandler<GetCustomersCompletedEventArgs>(client_GetCustomersCompleted);
            client.GetCustomersAsync();
        }

        void client_GetCustomersCompleted(object sender, GetCustomersCompletedEventArgs e)
        {
            this.Customer = e.Result;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

Jeg forstår udmærket godt, hvad det er der sker i den klasse, men er, som skrevet, bare i tvivl om, hvordan man "behandler" lister?

Min CustomerView.xaml.cs ser således ud:

public partial class CustomerView : Page
    {
        CustomerViewModel customerViewModel = new CustomerViewModel();

        public CustomerView()
        {
            InitializeComponent();
            this.DataContext = customerViewModel;
            Loaded += new RoutedEventHandler(CustomerView_Loaded);
        }

        void CustomerView_Loaded(object sender, RoutedEventArgs e)
        {
            customerViewModel.GetCustomers();
        }
    }

... og som sagt fungerer det fint hvis jeg bare skal have en enkelt Customer ud.

Nogen der kan 'enlighten' mig her? :) I må sige til, hvis der er nogle ting jeg skal uddybe.

På forhånd tak!
Avatar billede bmdk Nybegynder
23. september 2009 - 21:07 #1
Efter lidt prøven frem og tilbage og at have læst lidt artikler/tutorials er jeg kommet frem til noget lign. dette:

CustomerViewModel:

public class CustomerViewModel : INotifyPropertyChanged
    {
        private Customer _customer = null;
        private ObservableCollection<Customer> _customers = null;

        public Customer Customer
        {
            get { return _customer; }
            set
            {
                this._customer = value;
                RaisePropertyChanged("Customer");
                RaisePropertyChanged("AllCustomers");
            }
        }

        public ObservableCollection<Customer> Customers
        {
            get { return _customers; }
            set
            {
                this._customers = value;
                RaisePropertyChanged("Customers");
            }
        }

        public void FetchCustomers()
        {
            CustomerServiceClient client = new CustomerServiceClient();
            client.GetCustomersCompleted += new EventHandler<GetCustomersCompletedEventArgs>(client_GetCustomersCompleted);
            client.GetCustomersAsync();
        }

        void client_GetCustomersCompleted(object sender, GetCustomersCompletedEventArgs e)
        {
            ObservableCollection<Customer> c = new ObservableCollection<Customer>();
            foreach (Customer cust in e.Result)
            {
                c.Add(cust);
            }
            Customers = c;
        }
#region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

.. og på mit Customer view ser det således ud:

public partial class CustomerView : UserControl
    {
        CustomerViewModel viewModel = new CustomerViewModel();
        public CustomerView()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(CustomerView_Loaded);
            this.DataContext = viewModel;
        }

        void CustomerView_Loaded(object sender, RoutedEventArgs e)
        {
            viewModel.FetchCustomers();
        }
    }

Binder på denne måde:

<UserControl x:Class="Biobooking.View.Views.CustomerView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <ListBox x:Name="CustomerList" Margin="5">
            <ListBox.ItemTemplate>
                <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Customer.Name, Mode=TwoWay}"></TextBlock>
                </StackPanel>
                    </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

Har prøvet at debugge det lidt og det viser sig, at på mit View, efter at have kaldt metoden FetchCustomers(), er alt på DataContext lig med null..

Kan bare absolut ikke se hvorfor :(
Avatar billede bmdk Nybegynder
23. september 2009 - 21:08 #2
hov.. "AllCustomers" er fra en gammel test ;) se bort fra den..
Avatar billede bmdk Nybegynder
23. september 2009 - 23:03 #3
Fandt selv ud af det :)

Skulle blot sætte ItemsSource til min property på ViewModel og så kunne jeg ellers binde som jeg havde lyst ;)

Mit eksempel i XAML:

<Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical">
            <Button Opacity="30" Click="Button_Click" Content="Click me" Margin="30" Width="150" Height="50"></Button>
            <ListBox ItemsSource="{Binding Path=Customers}" x:Name="test" Height="200" Margin="5">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Firstname}"></TextBlock>
                            <TextBlock Text=" "></TextBlock>
                            <TextBlock Text="{Binding Lastname}"></TextBlock>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>
    </Grid>
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester