GridViewColumn将内容绑定到方法

时间:2017-05-20 13:56:02

标签: c# wpf mvvm

简化学生班

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()获取的数据。有没有办法怎么做并将参数传递给这个方法?

1 个答案:

答案 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查询的开销是多少。