2012-06-07 19 views
5

Jestem nowy w WPF i próbuję zbudować przykładową aplikację wykorzystującą framework MVVM. Moja aplikacja ma plik xaml, który ma kilka pól tekstowych do wprowadzania informacji o kliencie, pole kombi do wyświetlania stanów i przycisk zapisu. Całe archiwum danych wykonuje się za pomocą narzędzia ViewModel (CustomerViewMode), które ma odniesienie do modelu (klienta), zawierającego wymagane pola i ich Getter, setery. ViewModel ma właściwość CustomerList. Po kliknięciu przycisku Zapisz chcę wyświetlić właściwości FirstName i LastName Klienta w Liście List. Tutaj jest problem. I debugowałem kod, (Kliknij wydarzenie przycisku w kodzie z tyłu), widzę, że CustomerList ma pierwszy obiekt klienta ze wszystkimi szczegółami, ale nie jest wyświetlany w polu listy. Mój kod to: Klient (model);Wiązanie ListBox z ViewModel w WPF

enter code here 
namespace SampleMVVM.Models 
{ 
class Customer : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private String _firstName; 
    private String _lastName; 
    private Address _customerAddress; 


    public String FirstName 
    { 
     get { return _firstName; } 
     set 
     { 
      if (value != _firstName) 
      { 
       _firstName = value; 
       RaisePropertyChanged("FirstName"); 
      } 
     } 
    } 

    public String LastName 
    { 
     get { return _lastName; } 
     set 
     { 
      if (value != _lastName) 
      { 
       _lastName = value; 
       RaisePropertyChanged("LastName"); 
      } 
     } 
    } 

    public Address CustomerAddress 
    { 
     get { return _customerAddress; } 
     set 
     { 
      if (value != _customerAddress) 
      { 
       _customerAddress = value; 
       RaisePropertyChanged("CustomerAddress"); 
      } 
     } 
    } 

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


} 

}

Adres (Model)

namespace SampleMVVM.Models 
{ 
class Address : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private string _addressLine1; 
    private string _addressLine2; 
    private string _city; 
    //private string _selectedState; 
    private string _postalCode; 
    private string _country; 






    public String AddressLine1 
    { 
     get { return _addressLine1; } 
     set 
     { 
      if (value != _addressLine1) 
      { 
       _addressLine1 = value; 
       RaisePropertyChanged(AddressLine1); 
      } 
     } 
    } 

    public String AddressLine2 
    { 
     get { return _addressLine2; } 
     set 
     { 
      if (value != _addressLine2) 
      { 
       _addressLine2 = value; 
       RaisePropertyChanged(AddressLine2); 
      } 
     } 
    } 

    public String City 
    { 
     get { return _city; } 
     set 
     { 
      if (value != _city) 
      { 
       _city = value; 
       RaisePropertyChanged(City); 
      } 
     } 
    } 




    public String PostalCode 
    { 
     get { return _postalCode; } 
     set 
     { 
      if (value != _postalCode) 
      { 
       _postalCode = value; 
       RaisePropertyChanged(PostalCode); 
      } 
     } 
    } 

    public String Country 
    { 
     get { return _country; } 
     set 
     { 
      if (value != _country) 
      { 
       _country = value; 
       RaisePropertyChanged(Country); 
      } 
     } 
    } 

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

}

CustomerViewModel:

namespace SampleMVVM.ViewModels 
{ 
class CustomerViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private Customer _customer; 
    RelayCommand _saveCommand; 
    private List<String> _stateList = new List<string>(); 
    private string _selectedState; 

    private ObservableCollection<Customer> _customerList = new ObservableCollection<Customer>(); 


    //public CustomerViewModel(ObservableCollection<Customer> customers) 
    //{ 
    // _customers = new ListCollectionView(customers); 

    //} 



    public Customer CustomerModel 
    { 
     get { return _customer; } 
     set 
     { 
      if (value != _customer) 
      { 
       _customer = value; 
       RaisePropertyChanged("CustomerModel"); 
      } 
     } 
    } 

    public List<String> StateList 
    { 
     get 
     { 

      return _stateList; 
     } 
     set { _stateList = value; } 

    } 

    public ObservableCollection<Customer> CustomerList 
    { 
     get 
     { 

      return _customerList; 
     } 
     set 
     { 
      if (value != _customerList) 
      { 
       _customerList = value; 
       RaisePropertyChanged("CustomerList"); 
      } 

     } 

    } 


    public CustomerViewModel() 
    { 
     CustomerModel = new Customer 
     { 
      FirstName = "Fred", 
      LastName = "Anders", 

      CustomerAddress = new Address 
      { 
       AddressLine1 = "Northeastern University", 
       AddressLine2 = "360, Huntington Avenue", 
       City = "Boston", 
       PostalCode = "02115", 
       Country = "US", 


      } 
     }; 

     StateList = new List<String> 
     { 
      "Alaska", "Arizona", "California", "Connecticut", "Massachusetts", "New Jersey", "Pennsylvania", "Texas" 
     }; 
     SelectedState = StateList.FirstOrDefault(); 


    } 

    public String SelectedState 
    { 
     get { return _selectedState; } 
     set 
     { 
      if (value != _selectedState) 
      { 
       _selectedState = value; 
       RaisePropertyChanged(SelectedState); 
      } 
     } 
    } 

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

     } 

}

CustomerInfo.xaml (zobacz)

<UserControl x:Class="SampleMVVM.Views.CustomerInfo" 
     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" 
     xmlns:ViewModels="clr-namespace:SampleMVVM.ViewModels"    
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 

<UserControl.DataContext> 
    <ViewModels:CustomerViewModel /> 
</UserControl.DataContext> 



<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition /> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 


    <!--Starting label--> 
    <TextBlock FontSize="18" FontFamily="Comic Sans MS" FontWeight="ExtraBlack" 
       Foreground="Navy" 
       Grid.Row="0" HorizontalAlignment="Center"> 
     <TextBlock.Text> 
      Customer Information: 
     </TextBlock.Text> 
    </TextBlock> 

    <TextBlock Text="First name: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
       Grid.Row="1" Width="80px" Height="50px" Margin="40,5,0,0"/> 
    <TextBox Text="{Binding CustomerModel.FirstName}" Grid.RowSpan="2" HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="1" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0" Name="fname"/> 

    <TextBlock Text="Last Name: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
       Grid.Row="2" Width="80px" Height="50px" Margin="40,5,0,0"/> 
    <TextBox Text="{Binding CustomerModel.LastName}" Grid.RowSpan="2" HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="2" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0" Name="lname"/> 

    <TextBlock Text="Address: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
       Grid.Row="3" Width="80px" Height="50px" Margin="40,5,0,0"/> 
    <TextBox Text="{Binding CustomerModel.CustomerAddress.AddressLine1}" Grid.RowSpan="2" HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="3" Grid.Column="1" Width="160px" Height="20px" Margin="20,5,0,0"/> 
    <TextBox Text="{Binding CustomerModel.CustomerAddress.AddressLine2}" Grid.RowSpan="2" HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="4" Grid.Column="1" Width="160px" Height="30px" Margin="20,5,0,0"/> 

    <TextBlock Text="City: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
       Grid.Row="5" Width="80px" Height="20px" Margin="40,5,0,0"/> 
    <TextBox Text="{Binding CustomerModel.CustomerAddress.City}" Grid.RowSpan="2" HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="5" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0"/> 

    <TextBlock Text="State: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
       Grid.Row="6" Width="80px" Height="20px" Margin="40,5,0,0"/> 
    <ComboBox Grid.RowSpan="2" HorizontalAlignment="Left" Name="listOfSates" 
       VerticalAlignment="Top" 
       Grid.Row="6" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0" 
       ItemsSource="{Binding Path=StateList}" 
       SelectedItem="{Binding Path=SelectedState}" 
       SelectionChanged="ComboBox_SelectionChanged" 
       > 


    </ComboBox> 

    <TextBlock Text="PostalCode: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
       Grid.Row="7" Width="80px" Height="20px" Margin="40,5,0,0"/> 
    <TextBox Text="{Binding CustomerModel.CustomerAddress.PostalCode}" Grid.RowSpan="2" HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="7" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0"/> 

    <TextBlock Text="Country: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
       Grid.Row="8" Width="80px" Height="20px" Margin="40,5,0,0"/> 
    <TextBox Text="{Binding CustomerModel.CustomerAddress.Country}" Grid.RowSpan="2" HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="8" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0"/> 

    <Button Content="Save" Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top" 
      Grid.Row="9" Width="50px" Height="20px" Name="savebtn" Margin="40,5,0,0" 
      Click="savebtn_Click"/> 


    <ListBox Name="cList" ItemsSource="{Binding Path=CustomerList}" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Grid.Row="1" Grid.Column="2" Grid.RowSpan="2" Width="200px" Height="300px" Margin="200,5,0,0"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <StackPanel> 
        <TextBlock Text="{Binding CustomerModel.FirstName}" 
          FontWeight="Bold" Foreground="Navy"/> 
        <TextBlock Text=", " /> 
        <TextBlock Text="{Binding CustomerModel.LastName}" 
          FontWeight="Bold" Foreground="Navy"/> 
       </StackPanel> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
</Grid> 

CustomerInfo (kod za klasą)

namespace SampleMVVM.Views 
{ 
/// <summary> 
/// Interaction logic for CustomerInfo.xaml 
/// </summary> 
public partial class CustomerInfo : UserControl 
{ 
    public CustomerInfo() 
    { 
     InitializeComponent(); 

     //checkvalue(); 
    } 

      private void savebtn_Click(object sender, RoutedEventArgs e) 
    { 
     ////Customer c = new Customer(); 
     ////c.FirstName = fname.Text; 
     ////c.LastName = lname.Text; 
     //CustomerViewModel cvm = new CustomerViewModel(); 
     //cvm.CustomerModel.FirstName = fname.Text; 
     //cvm.CustomerModel.LastName = lname.Text; 
     //List<CustomerViewModel> customerList = new List<CustomerViewModel>(); 
     //customerList.Add(cvm); 
     var viewModel = DataContext as CustomerViewModel; 


     if (viewModel != null) 
     { 

      //viewModel.ShowCustomerInfo(); 
      String strfname = viewModel.CustomerModel.FirstName; 
      String strname = viewModel.CustomerModel.LastName; 

      viewModel.CustomerList.Add(viewModel.CustomerModel); 
      String str1 = viewModel.CustomerList.FirstOrDefault().FirstName; 
      int i = viewModel.CustomerList.Count(); 
      //cList.ItemsSource = viewModel.CustomerList; 

     } 

    } 

    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     CustomerViewModel cvm = new CustomerViewModel(); 
     cvm.SelectedState = listOfSates.SelectedItem.ToString(); 
    } 




} 

}

ja po prostu nie mogę zrozumieć, gdzie będę źle ... Ktoś proszę o pomoc

Odpowiedz

2

I dla prawidłowego wiązania w ListBox.ItemTemplate:

<TextBlock Text="{Binding FirstName}" 
      FontWeight="Bold" Foreground="Navy"/> 
<TextBlock Text="{Binding LastName}" 
      FontWeight="Bold" Foreground="Navy"/> 

DataContext z ListBoxItem jest już klientem.

+0

Bardzo dziękuję:) ... zmieniłem wiązania wewnątrz listbox i zadziałało :) – user1318369

1

Twój problem jest w następującym wierszu kodu:

RaisePropertyChanged("CustomerList"); 

Nie działa dla zdarzeń dodawania/usuwania kolekcji. Spójrz na ObservableCollection and Item PropertyChanged.

Należy pamiętać, że w MVVM nie powinno być dużo kodu (jeśli jest) z kodem. Rozważ użycie poleceń.

3

Utworzenie nowej instancji obiektu CustomerModel tylko raz w kodzie (w konstruktorze Model widoku klienta). Dlatego stale aktualizujesz ten sam obiekt klienta, a nie tworzysz nowy.

Pod koniec swojej click obsługi należy zrobić

viewModel.CustomerModel = new Customer(); 

JEDNAK

Zamiast do obsługi kliknij należy mieć ICommand w widoku modelu za dodanie nowego klienta. Następnie powinieneś powiązać komendę swojego przycisku z ICommand w swoim modelu widoku.

+0

Zgadzam się, ale powinienem być 'viewModel.CustomerModel = new Customer();' – LPL

2

Wiązałeś nazwę CustomerLIst.FirstName, która nie jest walid, ponieważ innterconent sprawdzi listę nazw właściwości w boku źródła listbox. i jako że nie jest to ich, spowoduje to milczący błąd, ale nie pojawi się w interfejsie GUI, wystarczy, że podasz nazwę właściwości taką jak imię i nazwisko, które zadziała.

również oprócz wiązania w liście wszystkich rzeczy jest w porządku. po prostu zamień wiązanie listboksu jak poniżej.

<TextBlock Grid.Row="0" 
        Grid.Column="2" 
        HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        Text="List of Customers" /> 
     <ListBox Name="cList" 
       Grid.Row="1" 
       Grid.RowSpan="8" 
       Grid.Column="2" 
       ItemsSource="{Binding CustomerList}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel> 
         <TextBlock FontWeight="Bold" 
            Foreground="Black" 
            Text="{Binding FirstName}" /> 
         <TextBlock Text=", " /> 
         <TextBlock FontWeight="Bold" 
            Foreground="Black" 
            Text="{Binding LastName}" /> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
     <TextBlock Grid.Row="10" 
        Grid.Column="2" 
        HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        Text="{Binding CustomerList.Count, 
            StringFormat='Total Customers, ={0}'}" /> 

lepiej odbierać polecenia z wydarzeń.

+0

Dziękuję Jodha :) Twój kod pracował :) – user1318369