Привязка ObservableCollection к WPF ListBox - PullRequest
14 голосов
/ 10 ноября 2010

У меня есть код ниже:

    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 ]

20 голосов
/ 10 ноября 2010

Да, вам нужно как-то установить DataContext.Он не имеет DataContext, потому что окно не имеет DataContext, если он не установлен.ListBox получит DataContext, если вы сделаете это в конструкторе.

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

В противном случае вы можете использовать RelativeSource, ElementName и т. Д. В Binding, но я думаю, вы знали, что =)

4 голосов
/ 10 ноября 2010

Я обычно передаю модель представления в конструктор и устанавливаю текстовый текст для переданной модели представления. Затем ваша ObservableCollection может быть перемещена из представления и вставлена ​​в модель представления.Это отделяет ваше представление от вашей логики, а также позволяет вам модульно протестировать код модели представления.

public MainWindow(SomeViewModel viewModel) 
{ 
    DataContext = viewModel;

    InitializeComponent(); 
} 
2 голосов
/ 19 марта 2012

Попробуйте использовать шаблон MvvM, чтобы в представлении вы могли определить 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, будут поддерживать привязку в представлении обновленной без необходимости какого-либо кода позади в представлении каждый раз, когда в наблюдаемую коллекцию p_log добавляется новая строка.

...