2010-11-09 40 views
14

Tôi có đoạn code-behind dưới đây:ObservableCollection Binding để WPF ListBox

public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     ObservableCollection<int> sampleData = new ObservableCollection<int>(); 
     public ObservableCollection<int> SampleData 
     { 
      get 
      { 
       if (sampleData.Count <= 0) 
       { 
        sampleData.Add(1); 
        sampleData.Add(2); 
        sampleData.Add(3); 
        sampleData.Add(4); 
       } 
       return sampleData; 
      } 
     } 
    } 

XAML của tôi là:

<Window x:Class="Sandbox.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <ListBox ItemsSource="{Binding Path=SampleData}"/> 
    </Grid> 
</Window> 

Danh sách này không hiển thị các giá trị trong bộ sưu tập (hoặc bất cứ điều gì ở tất cả). Ai đó có thể chỉ ra sai lầm của tôi là gì?

Tôi có cần đặt rõ ràng DataContext không? Tôi nghĩ nếu không có thiết lập điều khiển sẽ chỉ sử dụng chính nó như là DataContext.

+0

Tính năng này có hoạt động nếu bạn đặt DataContext một cách rõ ràng không? – user200783

Trả lời

20

Có, bạn sẽ cần đặt DataContext bằng cách nào đó. Nó không có DataContext, vì Window không có DataContext trừ khi nó được thiết lập. ListBox sẽ nhận DataContext nếu bạn làm điều này trong hàm tạo.

public MainWindow() 
{ 
    InitializeComponent(); 
    this.DataContext = this; 
} 

Nếu không, bạn có thể sử dụng RelativeSource, ElementName vv trong Binding nhưng tôi đoán bạn biết rằng =)

4

Tôi thường vượt qua một viewmodel ở trên các nhà xây dựng và thiết lập các DataContext để viewmodel thông qua vào. Sau đó, ObservableCollection của bạn có thể được di chuyển ra khỏi khung nhìn và đặt trong viewmodel. Việc này sẽ tách chế độ xem của bạn khỏi logic của bạn và cũng cho phép bạn kiểm tra đơn vị mã xemmô hình.

public MainWindow(SomeViewModel viewModel) 
{ 
    DataContext = viewModel; 

    InitializeComponent(); 
} 
2

Cố gắng sử dụng pattern MVVM như vậy trong Xem bạn có thể xác định ListBox như thế này:

<ListBox ItemsSource="{Binding Path=Log, UpdateSourceTrigger=PropertyChanged}"/> 

Rồi View có thể được mà không có mã sau liên quan đến nguồn ràng buộc. Trong ViewModel liên quan bạn thêm một cái gì đó như thế này:

public class ViewModel : ViewModelBase 
{ 
    //... 
    private ObservableCollection<string> p_Log; 

    /// <summary> 
    /// A log of a starting process 
    /// </summary> 
    public ObservableCollection<string> Log 
    { 
     get { return p_Log; } 

     set 
     { 
      base.RaisePropertyChangingEvent("Log"); 
      p_Log.Add(value.ToString()); 
      base.RaisePropertyChangedEvent("Log"); 
     } 
    } 
    //.... 
    /// <summary> 
    /// Initializes this view model. 
    /// </summary> 
    /// <param name="mainWindowViewModel">The view model for this application's main window.</param> 
    private void Initialize(MainWindowViewModel mainWindowViewModel) 
    { 
     //... 
     p_Log = new ObservableCollection<string>(); 
    } 

và sau đó là các sự kiện quy định tại ViewModelBase sẽ giữ các ràng buộc trong Xem cập nhật, mà không cần bất kỳ mã sau trong giao diện bất cứ lúc nào một chuỗi mới được thêm vào p_log bộ sưu tập quan sát được.