Итак, я создаю программу, которая вытаскивает имена таблиц и полей из базы данных Microsoft Access и помещает их в два разных элемента списка. В качестве теста для моей привязки я установил одинаковые настройки обоих ящиков (просто простая копия/вставка, потому что я обогнал себя), и я получил имена таблиц для успешного связывания, но только с использованием lbTables.DataContext = this;
(я пытался использовать lbTables.SetBinding (ListBox.DataContextProperty, new Binding ("MDBtoCSV.MainWindow"));
, но это не так, по какой-то причине). DataContext, похоже, не наследует от окна над ним, которое из того, что я прочитал, - это то, что он должен делать.Предпочтительный/правильный способ привязки к MainWindow
Когда я начал пытаться привязать DataContext к lbFields в XAML, я нашел странную проблему. если я определяю и инициализирую коллекцию в одно и то же время, глобально (как показано ниже), private ObservableCollection<CheckedListItem<Table>> _listTables = new ObservableCollection<CheckedListItem<Label>>();
оба ListBox ведут себя так же, как и от них.
Но если я вместо этого инициализирую коллекцию в своем коде и использую lbTables.DataContext = this;
, тогда только lbTables заполняется, пока lbFields остается пустым. Есть ли предпочтительный метод или менее хрупкий метод для явного определения DataContext и ItemSource?
Ниже моя XAML:
<ListBox x:Name="lbFields" HorizontalAlignment="Left" Height="70" Margin="10,113,0,0" VerticalAlignment="Top" Width="240"
DataContext="{Binding ElementName=appMainWindow, Mode=OneWay}" ItemsSource="{Binding Path=ListTables, Mode=OneWay}">
</ListBox>
</Grid>
TL; DR: Почему бы DataContext не наследуется от окна? Почему не ListBox.DataContext = this
действуют так же, как версия XAML?
Edit:
private ObservableCollection<CheckedListItem<Table>> _listTables;// = new ObservableCollection<CheckedListItem<Table>>();
public ObservableCollection<CheckedListItem<Table>> ListTables
{
get { return _listTables; }
private set { _listTables = value;}
}
public class CheckedListItem<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool isChecked;
private T item;
private string name;
public string Name { get; set; }
public CheckedListItem() { }
public CheckedListItem (T item, bool isChecked = false)
{ this.item = item;
this.isChecked = isChecked;}
public T Item
{ get { return item; }
set
{ item = value;
NotifyPropertyChanged("Item");}
}
public bool IsChecked
{ get { return isChecked; }
set
{ isChecked = value;
NotifyPropertyChanged ("IsChecked");}
}
public class Table
{ public string name { get; set; }
private ObservableCollection<string> _listFields = new ObservableCollection<string> (
new string[]{"null","null","null","null"});
public ObservableCollection<string> ListFields { get { return _listFields; } set { _listFields = value; } }
}
Я в основном придерживаюсь MVVM, и все мои свойства реализуют INotifyPropertyChanged, за исключением моего самого верхнего свойства, которое содержит список имен таблиц. Он находится в главном окне, и я не уверен, как реализовать INotifyPropertyChanged, кроме наследования его в классе. Кроме того, вы по-прежнему неявно предполагаете DataContext, который, прежде всего, я считаю своей проблемой. –
Пока ваши объекты 'ViewModel' реализуют' INotifyPropertyChanged', а ваш набор 'set {...}' вашего свойства правильно запускает обработчик событий, все будет в порядке. 'ObservableCollection' обрабатывает его также. Ваш «DataContext» подразумевается с помощью «Window.DataContext», поэтому создается «MainWindowViewModel», который должен содержать все модели представлений, которые необходимо отобразить. –
Erik
За исключением DataContext неявно назначается. Если я удалю 'lbTables.DataContext = this;' из моего кода, я потеряю привязку для lbTables, пока поддерживает lbFields, потому что его DataContext жестко закодирован в XAML. –