我正在学习MVVM并正在为练习创建应用
我正在尝试创建一个应用程序,您可以添加并查看学生的一切正常,直到我尝试将Observable Collection与ViewModel的其余部分分开,并能够将其用于其他ViewModel。
我的问题是如何使用ObservableCollection或每个View中任何ViewModel之外的任何其他类型的数据持有者?
告诉我你是否需要代码?
这是包含数据的类 在解决方案资源管理器中,文件的路径是数据/数据库
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>
搜索窗口急剧代码
public partial class Search: Window
{
public Search()
{
InitializeComponent();
}
}
我在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一切正常但是如果我尝试在XAML中为特定控件设置DataContext onlt那么我没有得到列表不显示数据
这是我上传项目的Skydrive的链接
如果代码隐藏就是这一切
InitializeComponent();
DataContext = new Data.StudentDatabase();
但如果我不使用代码隐藏并在XAML中这样做就没有任何反应
DataContext="{Binding Path=Data.StudentDatabase}"
我显然在这里遗漏了一些东西
答案 0 :(得分:1)
这是一个应用程序设计问题。如果要共享包含所有视图的集合,则需要将其放在应用程序视图模型中,例如MainViewModel
。此外,您需要从所有视图中访问它,为此,您可以在要显示集合的每个视图的视图模型中引用MainViewModel
。另一种方法是共享MainViewModel
实例,您可以将其保存在应用程序资源中。如果您使用Galasoft MVVMLight Toolkit
,则可以通过MainViewModel
访问ViewModelLocator
。希望这个想法有所帮助......
修改强>
添加代码后,我可以注意到您对ViewModel
模式的理解不是很好。您的班级StudentObservableCollection
应该是StudentViewModel
,它应该只有学生属性。此外,您还需要一个类来管理StudentViewModel
。在本课程中,您应该拥有StudentsData
或ObservableCollection<StudentViewModel>
,在此课程中您还可以使用SelectedStudent
类型StudentViewModel
等其他属性。就像我在原始答案中所说的那样,如果学生的集合应该在应用程序中的几个视图中可用,您可以在全局视图模型中创建它。
答案 1 :(得分:0)
乔治,
如果您希望在整个应用程序中共享类似数据库的内容,可以在MainWindow中创建资源,并且在MainWindow可视树下定义的任何控件都可以访问该资源。
所以在MainWindow 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>