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. Надеюсь, что это поможет вам

Другие вопросы по тегам