简体   繁体   中英

WPF ItemsSource works in code-behind but not in XAML

I have a simple combobox with a checkbox inside as such:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="158,180,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" ItemsSource="{Binding collection}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <CheckBox Content="{Binding Name}"></CheckBox>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

The datacontext is simply the code behind, and to test it I use the following code:

public ObservableCollection<Foo> collection { get; set; }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        collection = new ObservableCollection<Foo>();
        this.comboBox1.ItemsSource = collection;
        Foo f = new Foo("DSD");
        collection.Add(f);
    }

When I set the ItemsSource as I have in the code, then it works fine, but I want to set the ItemsSource in the Xaml, however it does not work using the Xaml above. I have also tried setting it to Path = "". Anybody know why?

Thanks

You need to assign DataContext to the control. something like:

var window = new Window1();
window.DataContext = new WindowDC();
window.Show();

where Window1 class contains the combobox, and WindowDC is like:

public class WindowDC
{ 
   public ObservableCollection<Foo> collection { get; set; }
}

That's how this will work.

What you actually do is that you place collection into control class, and set your datacontext for combobox only.

But, for testing purposes, you can still set Combox.Datacontext in control constuctor.

Bindings in WPF always have a Source. If you don't specify the source in the binding itself, then it will implicitly use the DataContext of the control or an ancestor of it. So if you want to bind to properties in your codebehind file, you have to set the DataContext to an object of the class which contains the collection property. In your case this is the instance of the Window ( this ).

DataContext = this;

As the commentor pointed out, it's not considered good style putting business logic or data inside the code behind file. So consider writing a separate class which contains your collection property and which you can use to initalize your DataContext . If you are writting bigger applications you should take a look at patterns like MVVM, which uses databinding to provide a better separation between your view and your model.

Edit: Changed ordering and incorporated feedback

Make sure there exist a public property collection in your code behind.

in the code behind also do this.DataContext = this

Finally implement INotifyPropertyChanged to tell the view that you have changed the collection once you add items in it

public ObservableCollection<Foo> Collection 
{ 
get
    {
    return collection;
    }
 set
    {
    collection = value;
    OnPropertyChanged("Collection");

    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        collection = new ObservableCollection<Foo>();
        //this.comboBox1.ItemsSource = collection;
        Foo f = new Foo("DSD");
        collection.Add(f);
        OnPropertyChanged("Collection");
    }

It is working when you are setting combo's item source in code behind because the source of combo is getting updated like wise to set the item source in XAML you have to make a property with INotifyPropertyChanged that keep update the combo's itemsource every time you update your collection via this property..

 private ObservableCollection<Foo> _Collection;
 public ObservableCollection<Foo> Collection 
{ 
get
{
return collection;
}
 set
{
collection = value;
OnPropertyChanged("Collection");
}

Now as you are filling collection on button click you just have to set that collection in the property as..

 _Collection = new ObservableCollection<Foo>();
 Foo f = new Foo("DSD");
 _Collection .Add(f);
  Collection = _Collection ; //here property call OnPropertyChange 

like wise you can provide data to any control. It is jsut the game of INotifyPropertyChanged property. Hope this will help you

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