【问题标题】:How to hide last child control in ItemsControl如何隐藏 ItemsControl 中的最后一个子控件
【发布时间】:2018-03-21 15:17:26
【问题描述】:

我有一个 ItemsControl,它使用 ObservableCollection 作为其 ItemsSource。

ObservableCollection 持有 Student 类型。

ObservableCollection 是在我的 ViewModel 中使用此方法构建的:

private void AddStudentToCollection()
{
  List<ClassMates> classMates = new List<ClassMates>();
  classMates.Add(SelectedClassMate);
  Student = new Student(classMates); // Setting the VM property here
  Id = Student.ID; // Setting the VM property here
  StudentCollection.Add(Student);
 }
}

以下是视图模型中的相关属性:

private Student student;
public Student Student
{
 get
 {
  return this.student;
 }
 set
 {
  this.student = value;
  OnPropertyChanged("Student");
  }
 }

 private int id;
 public int ID
 {
   get
   {
     return this.id;
   }
   set
   {
    this.id = value;
    OnPropertyChanged("ID");
    }
   }

private ObservableCollection<Student> studentCollection;
public ObservableCollection<Student> StudentCollection
{
 get
 {
  if (studentCollection == null)
    studentCollection = new ObservableCollection<Student>();
  return this.studentCollection;
 }
}

这是我的学生课:

public class Student : INotifyPropertyChanged
{
 public Student(List<ClassMates> ClassMates)
 {
  this.ClassMates = ClassMates;
 }

 public IList<ClassMates> ClassMates { get; set; }

 private int id;
 public int ID
 {
  get
  {
    return this.id;
  }
  set
  {
   this.id = value;
   OnPropertyChanged("ID");
  }
 }

因此,每次用户从 Grid 中选择一行时,都会调用这个 AddStudentToCollection() 方法。将添加的 Student 是实际选择的行。

ItemsControl 包含 Grid 控件,Grid 控件如下所示:

[------] 1

[------] 1

[------] 1

这里的 1 是 View Model 中的 ID 属性。

网格将包含更多信息,但这是基本布局。 ItemsControl 将随着 ObservableCollection 的增长而增长。

我想要完成的工作:

如果 Grid 是 ItemsControl 的最后一个元素,我想隐藏最后一个 ID 属性(最后一个 1)。

所以我真的想要上面的例子

[----] 1

[----] 1

[----]

现在,我很清楚,在我的项目的视图模型中拥有一个属性而不在学生类中拥有一个单独的属性更有意义。

我想知道是否有一种干净的 MVVM 方式来完成此任务。 这是我的 XAML:

<ItemsControl ItemsSource="{Binding StudentCollection}">
  <ItemsControl.ItemTemplate>
   <DataTemplate>
    <Grid>
     <Grid.ColumnDefinitions>
      <ColumnDefinition Width="100"/>
      <ColumnDefinition Width="*"/>
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
      <RowDefinition Height="70"/>
      <RowDefinition Height="*"/>
     </Grid.RowDefinitions>
     <Label Grid.Row="1" Grid.Column="1"
      // This is the text of the Label, where the ID is actually displayed.
      Content="{Binding Path=DataContext.ID, RelativeSource={RelativeSource AncestorType=ItemsControl}, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
   </DataTemplate>
  </ItemsControl.ItemTemplate>
 </ItemsControl>

【问题讨论】:

  • 那么每个item前面会显示相同的ID?因为标签是绑定到来自 VM 的 ID,而不是 Student 类中的 ID!?
  • 是的,没错。
  • 所以 Vm 的 ID 总是包含 ObservableCollection 中的项目数,对吧?
  • 不是直接属性,但它会知道,是的

标签: c# wpf mvvm


【解决方案1】:

如果您不想将属性添加到返回 boolStudent 类,您可以在视图中使用多转换器,将当前项目的索引与显示的项目总数进行比较在ItemsControl:

class MultiConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        ItemsControl ic = (ItemsControl)values[0];
        object item = values[1];

        return ic.Items.IndexOf(item) == ic.Items.Count - 1 ? Visibility.Collapsed : Visibility.Visible;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

XAML:

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Grid>
            <Label Grid.Row="1" Grid.Column="1"  Content="{Binding Path=DataContext.ID, RelativeSource={RelativeSource AncestorType=ItemsControl}, UpdateSourceTrigger=PropertyChanged}">
                <Label.Visibility>
                    <MultiBinding>
                        <MultiBinding.Converter>
                            <local:MultiConverter />
                        </MultiBinding.Converter>
                        <Binding Path="." RelativeSource="{RelativeSource AncestorType=ItemsControl}" />
                        <Binding Path="." />
                    </MultiBinding>
                </Label.Visibility>
            </Label>
        </Grid>
    </DataTemplate>
</ItemsControl.ItemTemplate>

【讨论】:

  • 嗯,我只是得到一个空白字符串 - 所有的 ID 都是空白的。
  • StudentCollection 到底是什么?提出问题时应始终提供 MCVE 是有原因的:stackoverflow.com/help/mcve
  • 这是一个 ObservableCollection 的学生。 VM 中的 ID 属性将始终相同并分配给 Student.ID 属性。对于每个学生,它始终是 1 或 2 或 3 或其他任何值,但最后一个始终是空字符串。
  • 嗯,这当然适合我。同样,如果您需要任何进一步的帮助,请提供您的问题的 repo。
  • 效果很好。我只是稍微修改了一下。我只传入 ItemsSource 而不是整个 ItemsControl,我使用转换器参数来确定要隐藏的索引。
猜你喜欢
  • 1970-01-01
  • 2012-01-25
  • 2013-12-26
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多