绑定ObservableCollection到WPF ListBox

15
我有以下的后端代码:
    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代码如下:

<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>
  • 列表没有显示集合中的值(或者根本就没有显示任何东西)。有人能指出我的错误吗?
  • 我需要显式地设置DataContext吗?我认为如果没有设置,控件会只使用自身作为DataContext。

如果你明确设置DataContext,它会起作用吗? - user200783
3个回答

22

是的,你需要设置 DataContext。它没有 DataContext,因为 Window 没有 DataContext,除非它被设置。如果你在构造函数中这样做,ListBox 将会得到 DataContext。

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

否则你可以在绑定中使用RelativeSource、ElementName等,但我猜你已经知道了 =)


4

我通常会在构造函数中传递一个viewmodel,并将datacontext设置为传入的viewmodel。然后,您的ObservableCollection可以从视图中移出并放置在viewmodel中。这样可以将视图与逻辑分离,并允许您对viewmodel代码进行单元测试。

public MainWindow(SomeViewModel viewModel) 
{ 
    DataContext = viewModel;

    InitializeComponent(); 
} 

2

尝试使用MvvM模式,这样在View中,您可以像这样定义ListBox:

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

然后,视图可以没有与绑定源相关的代码。在相关的ViewModel中,您可以添加类似以下内容的代码:

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

然后,在ViewModelBase中定义的事件将保持与View的绑定更新,无需在视图中添加任何代码,每当向可观察集合p_log添加新字符串时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接