2012-06-07 44 views
5

Tôi mới sử dụng WPF và cố gắng xây dựng một ứng dụng mẫu bằng cách sử dụng khung MVVM. Ứng dụng của tôi có tệp xaml có một số hộp văn bản để nhập thông tin khách hàng, hộp tổ hợp để hiển thị trạng thái và nút lưu. Tất cả các databinding được thực hiện thông qua ViewModel (CustomerViewMode) có tham chiếu đến Model (Customer), chứa các trường bắt buộc và Getter, setters của chúng. ViewModel có thuộc tính CustomerList. Khi nhấp vào nút lưu, tôi muốn hiển thị thuộc tính FirstName và LastName của Khách hàng trong ListBox. Đây là nơi mà vấn đề là. Tôi đã sửa lỗi mã, (Nhấp vào sự kiện của nút trong mã phía sau), tôi có thể thấy rằng Danh sách khách hàng có đối tượng Khách hàng đầu tiên với tất cả chi tiết của nó, nhưng nó không được hiển thị trong hộp danh sách. Mã của tôi là: Khách hàng (Người mẫu);Ràng buộc ListBox với ViewModel trong 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)); 
     } 
    } 


} 

}

Địa chỉ (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)); 
     } 
    } 

     } 

}

01.235.

CustomerInfo.xaml (view)

<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 (Mã số đằng sau lớp)

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(); 
    } 




} 

}

Tôi chỉ không thể hiểu nơi tôi đi sai ... Có người xin vui lòng giúp

Trả lời

2

Và cho đúng ràng buộc trong ListBox.ItemTemplate:

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

Các DataContext của ListBoxItem là một khách hàng rồi.

+0

Cảm ơn bạn rất nhiều:) ... i thay đổi các ràng buộc bên trong hộp danh sách và nó hoạt động :) – user1318369

1

Sự cố của bạn nằm trong dòng mã sau:

RaisePropertyChanged("CustomerList"); 

Nó không hoạt động để thu thập thêm/xóa sự kiện. Hãy xem ObservableCollection and Item PropertyChanged.

Hãy nhớ rằng trong MVVM, bạn không nên có nhiều mã (nếu có) ở mã phía sau. Xem xét sử dụng lệnh.

3

Bạn chỉ tạo một phiên bản mới của đối tượng CustomerModel một lần trong mã của bạn (trong trình tạo mô hình Chế độ xem khách hàng). Vì vậy, bạn liên tục cập nhật cùng một đối tượng khách hàng thay vì tạo một đối tượng mới.

Vào cuối handler nhấp chuột của bạn, bạn nên làm một

viewModel.CustomerModel = new Customer(); 

TUY NHIÊN

Thay vì có một handler nhấp chuột bạn nên có một ICommand trong mô hình xem của bạn cho thêm khách hàng mới. Sau đó, bạn nên liên kết với lệnh của nút của bạn để ICommand trong mô hình xem của bạn.

+0

Đồng ý, nhưng phải là 'viewModel.CustomerModel = new Customer();' – LPL

2

bạn đã ràng buộc CustomerLIst.FirstName không phải là không hợp lệ bởi vì innterconent sẽ kiểm tra danh sách khách hàng tên thuộc tính bên cạnh hộp danh sách các mục. và vì nó không phải của họ sau đó nó sẽ nâng cao một lỗi im lặng nhưng không hiển thị vào GUI, những gì bạn cần làm là chỉ cần cung cấp các propertyname như firstname và lastname mà sẽ làm việc.

ngoài việc ràng buộc trong hộp danh sách, mọi thứ khác đều ổn. chỉ thay thế bạn ràng buộc danh sách như dưới đây.

<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}'}" /> 

tốt hơn để thực hiện lệnh diễn ra sự kiện.

+0

Cảm ơn rất nhiều Jodha :) mã của bạn đã làm việc :) – user1318369

Các vấn đề liên quan