开发者

Binding ObservableCollection to WPF ListBox

开发者 https://www.devze.com 2023-01-24 11:34 出处:网络
I have the below code-behind: public partial class MainWindow : Window { public MainWindow() { InitializeComponent();

I have the below code-behind:

    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;
            }
        }
    }开发者_开发知识库

My xaml is:

<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>

The list doesn't display the values in the collection (or anything at all). Can someone point out what my mistake is?

Do I need to set the DataContext explicitly? I thought if none is set the control will just use itself as the DataContext.


Yes, you'll need to set the DataContext somehow. It doesn't have a DataContext, because the Window doesn't have a DataContext unless it is set. The ListBox will get the DataContext if you do this in the constructor.

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

Otherwise you can use RelativeSource, ElementName etc. in the Binding but I guess you knew that =)


I usually pass a viewmodel in on the constructor and set the datacontext to the viewmodel passed in. Then your ObservableCollection can be moved out of the view and put in the viewmodel. This separates your view from your logic and also allows you to unit test the viewmodel code.

public MainWindow(SomeViewModel viewModel) 
{ 
    DataContext = viewModel;

    InitializeComponent(); 
} 


Try to use the MvvM patern so in the View you can define the ListBox like this:

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

Then the View can be without code behind related to the binding source. In the related ViewModel you add something like this:

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

and then the events defined in ViewModelBase will keep the binding in the View updated, without need of any code behind in the view any time a new string is added to the observable collection p_log.

0

精彩评论

暂无评论...
验证码 换一张
取 消