【问题标题】:WPF - Freeze the first item in WPF nested ListViewWPF - 冻结 WPF 嵌套 ListView 中的第一项
【发布时间】:2018-01-19 08:56:11
【问题描述】:

我有一个 ListView,其中包含一个文本块和一个 ListView 作为数据模板。下面是我的代码。

<ListView x:Name="DoctorsList" Grid.Column="1"  VerticalContentAlignment="Top">
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding DoctorName}" HorizontalAlignment="Center"/>
                    <ListView ItemsSource="{Binding AppointmentDetails}">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Vertical" Margin="2 2 0 0">
                                    <TextBlock Text="{Binding PatientName}" />
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
</ListView>

在这里,我想在用户向下滚动时冻结列表顶部的医生姓名。现在,如果向下滚动,医生姓名将被隐藏。我的目标是如果用户向下滚动,只需滚动患者姓名。医生的名字必须在顶部冻结。这样用户就可以与各自的医生一起查看完整的患者名单,而不会感到困惑。请帮忙。

【问题讨论】:

  • 您可以将 ListView 与患者一起设置为固定高度。但这可能看起来很丑。
  • 也许您应该将数据转换成表格,其中医生是列标题。实际上,ListView 看起来像是一个奇怪的控制这个功能的选择。
  • @Marc 它将为每一列提供滚动条。是的,它看起来很丑,占用更多空间。
  • @MathivananKP 如果您不想更改整个布局,可以使用第三个 ListView,它只有医生。所以你有一个 ListView 只包含医生姓名和一个 ListView 只包含患者的 ListViews 作为孩子。
  • @Marc 尝试了另一种列表视图方法。它满足了我的要求。感谢您的帮助。

标签: wpf xaml listview datatemplate


【解决方案1】:

以下示例显示了如何将结构转换为 ListViewGridView,其中每一列都是医生。

假设源数据结构如下:

public class DoctorsVM
{
    public DoctorsVM()
    {
        Doctors = new List<Doctor>();
    }
    public ICollection<Doctor> Doctors { get; set; }
}

public class Doctor
{
    public Doctor()
    {
        AppointmentDetails = new List<AppointmentDetail>();
    }
    public string DoctorName { get; set; }

    public ICollection<AppointmentDetail> AppointmentDetails { get; set; }
}

public class AppointmentDetail
{
    public string PatientName { get; set; }
}

您可以创建以下转换:

public class DoctorAppointmentCollectionVM
{
    public DoctorAppointmentCollectionVM()
    {
        Doctors = new List<Doctor>();
        Entries = new List<DoctorAppointmentLineItem>();
    }

    public List<Doctor> Doctors { get; set; }

    public List<DoctorAppointmentLineItem> Entries { get; set; }
}
public class DoctorAppointmentLineItem
{
    public DoctorAppointmentLineItem()
    {
        AppointmentLine = new List<AppointmentDetail>();
    }

    public List<AppointmentDetail> AppointmentLine { get; set; }
}


public DoctorAppointmentCollectionVM DoctorsToLineCollection(DoctorsVM docs)
{
    var result = new DoctorAppointmentCollectionVM();

    for (int i = 0; i < docs.Doctors.Count; i++)
    {
        var doc = docs.Doctors.ElementAt(i);
        result.Doctors.Add(doc);
        for (int j = 0; j < doc.AppointmentDetails.Count; j++)
        {
            var appointment = doc.AppointmentDetails.ElementAt(j);
            DoctorAppointmentLineItem patientArray;
            if (j >= result.Entries.Count)
            {
                patientArray = new DoctorAppointmentLineItem();
                patientArray.AppointmentLine.AddRange(Enumerable.Range(0, docs.Doctors.Count).Select(x => (AppointmentDetail)null));
                result.Entries.Add(patientArray);
            }
            else
            {
                patientArray = result.Entries[j];
            }
            patientArray.AppointmentLine[i] = appointment;
        }
    }
    return result;
}

并创建一个列表视图如下:

<ListView x:Name="lv1" ItemsSource="{Binding Entries}" Loaded="lv1_Loaded">
    <ListView.View>
        <GridView x:Name="gv1">
        </GridView>
    </ListView.View>
</ListView>

用加载的事件为每个医生创建一列

private void lv1_Loaded(object sender, RoutedEventArgs e)
{
    var data = lv1.DataContext as DoctorAppointmentCollectionVM;
    if (data != null)
    {
        gv1.Columns.Clear();
        for (int i = 0; i < data.Doctors.Count; ++i)
        {
            gv1.Columns.Add(new GridViewColumn
            {
                Header = data.Doctors[i].DoctorName,
                DisplayMemberBinding = new Binding(string.Format("AppointmentLine[{0}].PatientName", i)),
            });
        }
    }
}

这假设一组静态数据,如果数据应该在初始加载后动态更改,则需要添加更多逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 2013-09-03
    • 2015-01-16
    • 2014-06-25
    • 2015-09-22
    相关资源
    最近更新 更多