2013-11-25 101 views
1

我學習MVVM和做練習從數據類將數據傳遞到一個視圖

我試圖讓一個應用程序,您可以添加和查看學生的一切正常,直到我試圖分開創建一個應用程序從ViewModel的其餘部分獲取Observable集合,並能夠使用其他ViewModel。

我的問題是如何使用ObservableCollection或任何ViewModel之外的任何其他類型的數據持有者?

如果您需要密碼,請告訴我嗎?

這裏是在Solution Explorer中的數據 類的文件路徑爲數據/數據庫

public class StudentDatabase 
{ 
    #region Defining and Populating an ObservableCollection 
    // Defining an observable collection to hold the students 
    private ObservableCollection<Student> studentData; 

    // Populating the ObservableCollection 
    public StudentDatabase() 
    { 
     studentData = new ObservableCollection<Student>() 
     { 
      new Student(){Name="John", Surname="Smith", Age=17}, 
      new Student(){Name="Barbara", Surname="Johnson", Age=16} 
     }; 
    } 

    // Defining and setting the field for the Observable collection 
    public ObservableCollection<Student> StudentData 
    { 
     get { return studentData; } 
     set { RaisePropertyChanged("studentData"); } 
    } 
    #endregion 
    #region RaisePropertyChange implementation 
    /// <summary> 
    /// INotifyPropertyChanged implementation: 
    /// A property notifies something that it has changed 
    /// and the other object get's the new data 
    /// </summary> 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void RaisePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 
} 

這裏是頁面的XAML,我想表明它

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="15*"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 

    <ListBox DataContext="{Binding Path=Data.StudentDatabase}" 
      ItemsSource="{Binding StudentData}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="Auto"/> 
        </Grid.ColumnDefinitions> 
        <TextBlock x:Name="Name" 
           Grid.Column="0" 
           Text="{Binding Name}"/> 
        <TextBlock x:Name="Surname" 
           Grid.Column="1" 
           Text="{Binding Surname}"/> 
        <TextBlock x:Name="Age" 
           Grid.Column="2" 
           Text="{Binding Age}"/> 
       </Grid> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
</Grid> 

和搜索窗升C代碼

public partial class Search: Window 
{ 
    public Search() 
    { 
     InitializeComponent(); 
    } 
} 

我在輸出該錯誤w^indow在Visual Studio

System.Windows.Data Error: 40 : BindingExpression path error: 'Data' property not found on 'object' ''StudentDatabase' (HashCode=2650314)'. BindingExpression:Path=Data.StudentDatabase; DataItem='StudentDatabase' (HashCode=2650314); target element is 'ListBox' (Name=''); target property is 'DataContext' (type 'Object') 

我想在列表框中的更新是動態的,所以我不包括更新按鈕

編輯:我已經更新了代碼,但我覺得我沒有做某事再次正確,有人能照亮我嗎?

編輯:如果我在代碼隱藏一切設置DataContext的是確定,但如果我嘗試onlt設置的DataContext在XAML特定的控制,然後我不明白列表不顯示數據

這裏是Skydrive,我上傳的項目

一個鏈接,如果代碼隱藏這是一切工作

InitializeComponent(); 
DataContext = new Data.StudentDatabase(); 

,但如果我不使用代碼隱藏,並做到在XAML像這樣的事情發生

DataContext="{Binding Path=Data.StudentDatabase}" 

我明顯缺少在這裏

+4

是的,我們需要的代碼 – geedubb

+0

@geedubb這是 –

回答

1

的東西它是一個應用程序設計問題。如果要共享包含所有視圖的集合,則需要將其放入應用程序視圖模型中,如MainViewModel。此外,您需要保持從所有視圖訪問該視圖,因此,您可能需要在要顯示該視圖的每個視圖的視圖模型中參考MainViewModel。另一種方式是共享MainViewModel實例,您可以將其保存在應用程序資源中。如果您使用Galasoft MVVMLight Toolkit,則可以通過ViewModelLocator訪問MainViewModel。希望這有助於想法...


編輯 加入你的代碼後,我注意到,你根本不瞭解很好的ViewModel模式。你的課StudentObservableCollection應該是StudentViewModel,它應該只有學生屬性。你還需要有一門課來管理StudentViewModel。在這個類,你應該有StudentsDataObservableCollection<StudentViewModel>,在這個類中也可能有像StudentViewModel類型的SelectedStudent其他屬性。就像我在我的原始答案中所說的那樣,如果學生的集合應該在應用程序中的多個視圖上可見,則可以使用全局視圖模型創建它。

0

喬治,

如果你正在尋找在你的應用程序共享類似的數據庫,你可以創建在主窗口的資源和主窗口的視覺樹下定義將有權訪問該資源的任何控制。

因此,在主窗口XAML,這樣做:

<Window.Resources> 
    <local:StudentDatabase x:Key="StudentDatabase"/> 
<Window>Resources> 

並在之後的任何控制,你可以這樣做<ListBox DataContext="{StaticResource StudentDatabase}"/>,這將使用您StudentDatabase。

我建議讓您的數據庫靜態不過,因爲每次你使用{StaticResource StudentDatabase}時,它會嘗試重新初始化這個類。使其變爲靜態,您將能夠創建一個實例並在整個應用程序中使用它。

當你想修改你的數據庫時,在代碼隱藏中,你可以在事件中調用類似StudentDatabase sDB = (DataContext as StudentDatabase);的東西,並且你將能夠調用你的函數來修改數據庫。

考慮一下:

<Window x:Class="Project.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:Project" 
    Title="Search" Height="300" Width="300"> 
<Window.Resources> 
    <local:StudentDatabase x:Key="StudentDatabase"/> 
</Window.Resources> 
<Grid> 
    <Grid.RowDefinitions> 

    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 

    </Grid.ColumnDefinitions> 
    <ListBox x:Name="StudentItemListBox" 
      Grid.Row="5" Grid.ColumnSpan="3" 
      DataContext="{StaticResource StudentDatabase}" 
      ItemsSource="{Binding StudentData}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="Auto"/> 
        </Grid.ColumnDefinitions> 
        <TextBlock Text="{Binding Name}"/> 
        <TextBlock Text="{Binding Surname}" 
            Grid.Column="1"/> 
        <TextBlock Text="{Binding Age}" 
            Grid.Column="2"/> 
        <!--Here go some other info about the students--> 
       </Grid> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <StackPanel> 
     <Button x:Name="Exit" 
       <!--TO-DO: Write an exit command-->/> 
    </StackPanel> 
</Grid> 
+0

如果我想使用AllStudents在其他視圖會發生什麼? –

+0

然後,你所要做的就是將你創建的'AllStudentsViewModel'對象的實例傳遞給你的視圖。 – Kcvin

+0

應該怎麼做 –

相關問題