简体   繁体   中英

Simple WPF DataBinding of a ListBox to an ObservableCollection of strings

Okay, I just don't get it. Please tell me why I get no items in my ListBox (should be the two strings "empty" and "stuff" right now ):

XAML:

<Window.DataContext>
    <Windows:SettingsWindowModel x:Name="model"/>
</Window.DataContext>

<Window.Resources>
    <DataTemplate x:Key="ListItemTemplate">
        <ListBoxItem Content="{Binding}"  />
    </DataTemplate>
</Window.Resources>

<ListBox Name="listBoxActivities" SelectionChanged="ListBoxActivitiesSelectionChanged"
 ItemsSource="{Binding Path=IgnoredActivities}"
 HorizontalAlignment="Left" VerticalAlignment="Top" MinHeight="40" MinWidth="200"
 Padding="5,100,5,0" Height="100" Margin="0,207,0,0" ItemTemplate="{StaticResource ListItemTemplate}" />

In SettingsWindowModel:

    private ObservableCollection<String> _ignoredActivities;
    public ObservableCollection<String> IgnoredActivities
    {
        get
        {
            if (_ignoredActivities == null)
            {
                // empty
                _ignoredActivities = new ObservableCollection<String>() { "empty","stuff" };
            }
            return _ignoredActivities;
        }
    }

Anything more you need to know? What did I forget?

EDIT: Maybe I should add that VisualStudio + ReSharper also show no underlines and compile errors. Not even warnings.

Sorry guys, the data was there all the time. The problem was in the visual details. The padding also got applied to a sub-container of the ListBox (or the items), therefore the items were not sitting at the top of the list. As I've but a height on the ListBox, the items always were below the visible height of the ListBox . Stange thing to debug. Thanks for your answers anyways!

1) You don't need to set the DataTemplate

2) Are you sure the DataContext of the view (aaaaa.xaml.cs) is the ViewModel (bbbbb.cs, contains IgnoredActivities)?

It should be like this:

aaaaa.xaml:

<ListBox ItemsSource="{Binding IgnoredActivities}" />

aaaaa.xaml.cs:

public partial class aaaaa : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new bbbbb();
    }
}

bbbbb.cs :

    public class bbbbb : INotifyPropertyChanged
    {
        public bbbbb()
        {
            IgnoredActivities.Add("empty");
            IgnoredActivities.Add("stuff");
        }

        private ObservableCollection<String> _ignoredActivities;
        public ObservableCollection<String> IgnoredActivities
        {
            get
            {
                if (_ignoredActivities == null)
                {
                    // empty
                    _ignoredActivities = new ObservableCollection<String>() { "empty","stuff" };
                }
                return _ignoredActivities;
            }
        }

            #region INotifyPropertyChanged Members

            public event PropertyChangedEventHandler PropertyChanged;
            private void RaisePropertyChanged(string _Prop)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(_Prop));
            }

            #endregion
    }
}

With this statement you are binding to a property "IgnoredActivities" in a control named "model" of your Window.

ItemsSource="{Binding ElementName=model, Path=IgnoredActivities}"

When working with ViewModels, set them as the DataContext of your control:

<ListBox ItemsSource="{Binding IgnoredActivities}">
    <ListBox.DataContext>
        <local:MyViewModel/>
    </ListBox.DataContext>        
</ListBox>

A binding with no source specified ("{Binding PathToMyPropert}") defaults to the control's DataContext, which is inherited from parent controls. So in your case, you could set your ViewModel to your Window's DataContext so it will be available to all its children:

<Window>
    <Window.DataContext>
        <local:MyViewModel/>
    </Window.DataContext>        

    <ListBox ItemsSource="{Binding IgnoredActivities}"/>    
</Window>

Get rid of that ElementName binding property. It's used to bind to WPF controls. Simply set ItemsSource={Binding IgnoredActivities}

Try it as follows:

<ItemsControl ItemsSource="{Binding Path=IgnoredActivities}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <ListBox />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
       <DataTemplate>
           <ListBoxItem Content="{Binding}"  />
       </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Try also setting the DataContext for the control in code behind.

Xaml       - <ListBox Name="myListBox" ItemsSource="{Binding IgnoredActivities}"/>    
CodeBehind - myListBox.DataContext=this;

确保DataContext包含IgnoredActivities并将ItemsSource绑定到它:

ItemsSource="{Binding IgnoredActivities}"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM