简化学生班
public class StudentListModel
{
public Guid Id { get; set; }
public string Login { get; set; }
public double CountPoints(Guid courseId)
{
var studentRepo = new StudentRepository();
var student = studentRepo.FindById(this.Id);
var evals = student.Evaluations.Where(e => e.Course.Id == courseId).ToList();
return evals.Sum(eval => eval.ObtainedPoints);
}
}
简化视图
<UserControl
DataContext="{Binding CourseDetailViewModel, Source={StaticResource ViewModelLocator}}">
...
<ListView ItemsSource="{Binding Detail.Students, UpdateSourceTrigger=PropertyChanged}">
<ListView.View>
<GridView>
<GridViewColumn Width="60" DisplayMemberBinding="{Binding Login} />
<GridViewColumn Width="60" x:Name="Points" />
</GridView>
</ListView.View>
</ListView>
...
</UserControl>
视图的DataContext
public class CourseDetailViewModel
{
private CourseDetailModel _detail;
public CourseDetailModel Detail
{
get { return _detail; }
}
}
CourseDetailModel: 方法 StudentListModel.CountPoints()的 courseId 参数来自此处。
public class CourseDetailModel
{
public Guid Id { get; set; }
}
在 Points 列中,我想显示从方法 CountPoints()获取的数据。有没有办法怎么做并将参数传递给这个方法?
答案 0 :(得分:1)
不完全是。
您可以做的是编写一个为您调用它的值转换器。由于我们需要绑定多个值(我们调用方法的StudentListModel
,以及方法的参数),我们必须使用带有多重绑定的多值转换器。
public class CountStudentCoursePointsConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var studentModel = (StudentListModel)values[0];
var courseId = (Guid)values[1];
return studentModel.CountPoints(courseId);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
// Can't convert back, don't try.
throw new NotImplementedException();
}
}
XAML
<!--
UpdateSourceTrigger=PropertyChanged tells the binding when to update the viewmodel
property. Well, a ListView cannot ever give your viewmodel a new collection of items,
so don't bother giving it that flag.
-->
<ListView ItemsSource="{Binding Detail.Students}">
<ListView.Resources>
<local:CountStudentCoursePointsConverter
x:Key="CoursePointsConverter"
/>
</ListView.Resources>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="60" DisplayMemberBinding="{Binding Login}" />
<GridViewColumn Width="60" x:Name="Points">
<GridViewColumn.DisplayMemberBinding>
<MultiBinding Converter="{StaticResource CoursePointsConverter}">
<!--
No path gives us the row item itself, an instance of
StudentListModel.
-->
<Binding />
<!--
The parent viewmodel is the DataContext of our ancestor
control, the ListView. That's a CourseDetailViewModel.
So go there with RelativeSource, get its Detail property,
and grab the Id.
-->
<Binding
Path="DataContext.Detail.Id"
RelativeSource="{RelativeSource AncestorType=ListView}"
/>
</MultiBinding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
您也可以从ToList()
删除CountPoints()
来电;没有必要在那里构建一个List。如果StudentRepository
实施IDisposable
,您也希望将其放在using
块中。
public double CountPoints(Guid courseId)
{
var studentRepo = new StudentRepository();
var student = studentRepo.FindById(this.Id);
return
student.Evaluations
.Where(e => e.Course.Id == courseId)
.Sum(eval => eval.ObtainedPoints);
}
总的来说,,最好从查询计算SQL中的点或LINQ to SQL的列表视图中填充列表视图。那是我的偏好。我不喜欢过早优化,但我想知道你对所有这些StudentRepository
查询的开销是多少。