2014-01-23 18 views
0

所以我正在構建一個程序,將表和字段名稱從Microsoft Access數據庫中取出並將它們放入兩個不同的Listbox項目。作爲一個測試我的綁定我有兩個框設置相同(只是一個簡單的複製/粘貼,因爲我超越自己),我得到了表名綁定成功,但只使用lbTables.DataContext = this;(我試圖使用lbTables.SetBinding (ListBox.DataContextProperty, new Binding ("MDBtoCSV.MainWindow"));但它doesn'由於某種原因工作)。 DataContext似乎不是從它上面的窗口繼承的,從我讀過的是它應該做的事情。首選/正確的方式來綁定到MainWindow

當我開始試圖在XAML的lbFields上關閉DataContext時,我發現了一個奇怪的問題。如果我在全局(如下)同時定義和初始化集合,那麼這兩個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版本相同?

編輯:

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; } } 
    } 

回答

0

我所做的一切都證明了,我所缺少的是MainWindow中的INotifyPropertyChanged。我以前無法弄清楚,但後來我發現this這是我一直在尋找三個月的東西。

0

我強烈建議你看一看的MVVM pattern example和使用,爲您的WPF和綁定。它使得所有這一切都變得更容易lot

我建議三個ViewModel類別:MainWindowViewModel,DatabaseTableViewModelDatabaseTableColumnViewModel。正如你可能想象,它們嵌套在每一個相應的,象這樣一些自己的特性:

class MainWindowViewModel : ViewModelBase 
{ 
    // Make sure you implement INotifyPropertyChanged and invoke on each property! 

    public string Title { get; set; } 

    public ObservableCollection<DatabaseTableViewModel> Tables { get; set; } 

    public DatabaseTableViewModel SelectedTable { get; set; } 
} 

class DatabaseTableViewModel : ViewModelBase 
{ 
    public string TableName { get; set; } 

    public ObservableCollection<DatabaseTableColumnViewModel> Columns { get; set; } 
} 

class DatabaseTableColumnTableViewModel : ViewModelBase 
{ 
    public string ColumnName { get; set; } 
    public string ColumnType { get; set; } 

    public DatabaseTableColumnViewModel SelectedColumn { get; set; } 
} 

所以,你的XAML綁定會是這個樣子:

<ListBox ItemsSource="{Binding Path=Tables}" 
     SelectedItem="{Binding Path=SelectedTable}"> 
</ListBox> 

<ListBox ItemsSource="{Binding Path=SelectedTable.Columns}" 
     SelectedItem="{Binding Path=SelectedTable.SelectedColumn}"> 
</ListBox> 

你將不得不工作一點點與此,以獲得多個選擇工作,但這是與綁定的一般想法。

您應該將MainWindow.DataContext設置爲MainWindowViewModel的實例。

+0

我基本上堅持MVVM和所有我的屬性實現INotifyPropertyChanged除了我最頂級的財產,擁有表名單的名單。它在主窗口中,我不確定如何實現INotifyPropertyChanged,而不是在類中繼承它。另外,你仍然隱含地假設DataContext,它主要是我相信我的問題的地方。 –

+0

只要你的'ViewModel'對象都實現了'INotifyPropertyChanged'並且你的屬性'set {...}'塊可以正確地調用事件處理程序,那麼你會好起來的。 'ObservableCollection '也可以處理它。你的'DataContext'隱含在'Window.DataContext'中,因此創建一個'MainWindowViewModel',它應該包含你需要顯示的所有視圖模型。 – Erik

+0

除了DataContext沒有被隱含分配。如果我從代碼隱藏中刪除了'lbTables.DataContext = this;',我丟失了lbFables的綁定,而lbFields卻維護它,因爲它的DataContext是用XAML硬編碼的。 –

相關問題