WPF ItemsSource работает в коде позади, но не в XAML
У меня есть простой выпадающий список с флажком внутри как таковой:
<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>
Datacontext - это просто код, и для его проверки я использую следующий код:
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);
}
Когда я устанавливаю ItemsSource, как в коде, он работает нормально, но я хочу установить ItemsSource в Xaml, однако он не работает с использованием Xaml выше. Я также попытался установить его в Path = "". Кто-нибудь знает почему?
Спасибо
4 ответа
Вам необходимо назначить DataContext для элемента управления. что-то вроде:
var window = new Window1();
window.DataContext = new WindowDC();
window.Show();
где Window1
класс содержит комбобокс, а WindowDC выглядит так:
public class WindowDC
{
public ObservableCollection<Foo> collection { get; set; }
}
Вот как это будет работать.
Что вы на самом деле делаете, это то, что вы размещаете collection
в контрольный класс, и установите ваш текст данных только для выпадающего списка.
Но для целей тестирования вы все равно можете установить Combox.Datacontext в управляющем конструкторе.
Привязки в WPF всегда имеют источник. Если вы не укажете источник в самой привязке, он будет неявно использовать DataContext элемента управления или его предка. Поэтому, если вы хотите связать со свойствами в вашем файле codebehind, вы должны установить DataContext для объекта класса, который содержит collection
имущество. В вашем случае это экземпляр окна (this
).
DataContext = это;
Как отметил комментатор, не считается хорошим стилем помещать бизнес-логику или данные в код позади файла. Так что подумайте о написании отдельного класса, который содержит ваши collection
собственность и которую вы можете использовать для инициализации вашего DataContext
, Если вы пишете большие приложения, вам следует взглянуть на шаблоны, такие как MVVM, которые используют привязку данных для лучшего разделения между вашим представлением и моделью.
Изменить: изменен порядок и включены отзывы
Убедитесь, что существует публичная собственность collection
в вашем коде позади.
в коде и делай this.DataContext = this
Наконец реализовать INotifyPropertyChanged
сказать, что вы изменили коллекцию после добавления в нее элементов
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");
}
Это работает, когда вы устанавливаете источник элемента комбо в коде позади, потому что источник комбо обновляется так же, как и для установки источника элемента в XAML, вы должны создать свойство с INotifyPropertyChanged, которое будет обновлять источник элементов комбо каждый раз, когда вы обновляете свою коллекцию через это свойство..
private ObservableCollection<Foo> _Collection;
public ObservableCollection<Foo> Collection
{
get
{
return collection;
}
set
{
collection = value;
OnPropertyChanged("Collection");
}
Теперь, когда вы заполняете коллекцию нажатием кнопки, вам нужно просто установить эту коллекцию в свойстве как..
_Collection = new ObservableCollection<Foo>();
Foo f = new Foo("DSD");
_Collection .Add(f);
Collection = _Collection ; //here property call OnPropertyChange
Также вы можете предоставить данные любому элементу управления. Это просто игра свойства INotifyPropertyChanged. Надеюсь, что это поможет вам