问题
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
回答1:
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.
回答2:
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
回答3:
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");
}
回答4:
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
来源:https://stackoverflow.com/questions/6292271/wpf-itemssource-works-in-code-behind-but-not-in-xaml