将ObservableCollection绑定到WPF ListBox

时间:2010-11-09 21:46:52

标签: wpf wpf-controls binding

我有以下代码隐藏:

    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。

3 个答案:

答案 0 :(得分:20)

是的,您需要以某种方式设置DataContext。它没有DataContext,因为除非设置了Window,否则Window没有DataContext。如果在构造函数中执行此操作,ListBox将获取DataContext。

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

否则你可以在Binding中使用RelativeSource,ElementName等,但我猜你知道=)

答案 1 :(得分:4)

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

public MainWindow(SomeViewModel viewModel) 
{ 
    DataContext = viewModel;

    InitializeComponent(); 
} 

答案 2 :(得分:2)

尝试使用MvvM patern,因此在View中你可以像这样定义ListBox:

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

然后View可以没有与绑定源相关的代码。在相关的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中的绑定保持更新,无论何时将新字符串添加到observable collection p_log中,都不需要在视图中隐藏任何代码。