2010-05-17 16 views
5

Piszę aplikację w WPF, używając zestawu narzędzi MVVm i mam problem z podpięciem viewmodelu i widoku.Jak ustawić datacontext formantu użytkownika

Model jest tworzony z wykorzystaniem struktury eno.net.

ViewModel:

public class CustomerViewModel 
    { 
     private Models.Customer customer; 
     //constructor 
     private ObservableCollection<Models.Customer> _customer = new ObservableCollection<Models.Customer>(); 
     public ObservableCollection<Models.Customer> AllCustomers 
     { 
      get { return _customer; } 

     } 
     private Models.Customer _selectedItem; 
     public Models.Customer SelectedItem 
     { 
      get { return _selectedItem; } 

     } 
     public void LoadCustomers() 
     { 
      List<Models.Customer> list = DataAccessLayer.getcustomers(); 
      foreach (Models.Customer customer in list) 
      { 
       this._customer.Add(customer); 
      } 
      } 
     } 

I widok (nie kod związany w tej chwili):

<UserControl x:Class="Customers.Customer" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      xmlns:vm ="clr-namespace:Customers.ViewModels" 
      d:DesignHeight="300" d:DesignWidth="300" 
      xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit" > 

    <Grid> 
     <toolkit:DataGrid ItemsSource="{Binding AllCustomers}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" AutoGenerateColumns="True"> 

     </toolkit:DataGrid> 

     <toolkit:DataGrid ItemsSource="{Binding SelectedItem.Orders}"> 

     </toolkit:DataGrid> 



    </Grid> 
</UserControl> 

I dataaccesslayer klasa:

class DataAccessLayer 
    { 
     public List<Customer> customers = new List<Customer>(); 

     public static List<Customer> getcustomers() 
     { 
      entities db = new entities(); 

      var customers = from c in db.Customer.Include("Orders") 
          select c; 
      return customers.ToList(); 
     } 


    } 

Problemem jest to, że brak danych jest wyświetlany po prostu dlatego, że kontekst danych nie jest ustawiony. Próbowałem to zrobić w kodzie z tyłu, ale nie działa. W każdym razie wolałbym to zrobić w pliku xaml. Innym problemem jest powiązanie SelectedItem - kod nigdy nie jest używany.

+0

W swoim kodzie masz właściwość AllCustomers w swoim modelu widoku, ale wiążą Cię klienci. – mak

+0

Czyściłem kod nieco i zrobiłem literówkę. Wiązanie w działającym kodzie jest oczywiście poprawne. – EVA

Odpowiedz

1

Czy jest to this czego szukasz?

+0

tak i nie. Muszę jakoś nazwać metodę getcustomers(). Czy powinienem to zrobić w konstruktorze viewmodel? Nie wydaje się bardzo dobry. – EVA

+0

Osobiście chciałbym wywołać metodę getcustomers() obiektu ViewModel w konstruktorze. Co według ciebie nie jest dobre? Kiedy widok renderuje, utworzy nową instancję ViewModel iw tym momencie chcesz, aby dane zostały pobrane, więc ma to sens dla konstruktora. –

+0

Co z konstrukcją xaml w zasobach? – EVA

5

Ponieważ używa się paradygmatu MVVM, chciałbym umieścić Twój ViewModel w konstruktorze dla widoku. Moim zdaniem/ViewModels zazwyczaj obserwować tą sekwencję zdarzeń:

  1. View Instanced
  2. przypadki Zobacz konstruktor ViewModel
  3. ViewModel inicjuje
  4. ViewModel uruchamia procedury pobierania danych (osobny wątek)
  5. ViewModel nazywa OnPropertyChanged (""), aby ostrzec, że coś się zmieniło; sprawdzić wszystko

My ViewModel jest instanced od kodzie XAML (przepraszam to w VB.NET, nie dostał się wokół do nauki C# na tyle dobrze, aby zaufać sobie z nim):

Public Sub New() 
    MyBase.New() 
    Me.DataContext = New EditShipmentViewModel(Me) 'pass the view in to set as a View variable 
    Me.InitializeComponent() 
End Sub 

Początkowo miałam nadzieję, że będzie mi się podobało coś takiego:

<UserControl> 
    <UserControl.DataContext> 
     <Local:EditShipmentViewModel> 
    </UserControl.DataContext> 
</UserControl> 

Ale to nie zadziałało, jakbym tego chciała.

Mam nadzieję, że trochę pomaga.

1

Ustawiłem datacontext viewmodel w taki sam sposób, w jaki zaobserwowałem Blend4 do. Oznacza to, że jeśli mój ViewModel nazywa MainViewModel, odwołać go w widoku jak:

<UserControl.Resources> 
    <local:MainViewModel x:Key="MainViewModelDataSource" /> 
</UserControl.Resources> 

<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource MainViewModelDataSource}}"> 
    ...view xaml stuff 

</Grid> 

również, jeśli ładowanie danych z bazy danych w konstruktorze Twojego viewmodel, nie zapomnij dodać metoda pomocnik wokół niego jak:

if (!DesignerProperties.GetIsInDesignMode(new DependencyObject())) 
     { 
      myCollection = new ObservableCollection<Blah>(something); 
     } 

tak że visual studio/Blend4 nie upaść próbując odzyskać dane z połączenia z bazą danych w projektancie. Osobiście ładuję dane w konstruktorze dość często, tylko dlatego, że potrzebuję go od razu, i że jest on buforowany w pamięci od uruchomienia.

:)

Powiązane problemy