gpt4 book ai didi

c# - 如何在 ItemsControl 中仅显示集合中的几个项目 - Silverlight

转载 作者:太空宇宙 更新时间:2023-11-03 11:31:07 25 4
gpt4 key购买 nike

我想知道是否有人知道如何在 ItemsControl 中仅显示绑定(bind)集合中的少数项目。无论是通过过滤 ICollectionView 还是其他方式。我确信我可以自己想出一个冗长的解决方案,但我想看看已经有什么了。

基本上,我有一个 ItemsControl 绑定(bind)到模型中包含的对象集合。我想做的是只显示其中的一些项目,然后有一个“查看更多”的超链接/按钮。这将显示整个项目集合。我希望能够使用 VSM 来表示“折叠”和“展开”状态,但我在思考如何初始化列表时遇到了问题。因为绑定(bind)是在 XAML 中创建的,所以我试图避免在代码隐藏中使用 Linq 来手动修改 ItemsSource 集合,如果所有其他方法都失败,这可能是一个解决方案。

如有必要,我可以显示一些代码,但我认为这不会比我的解释更有帮助。再说一遍,我只是希望有人在我尝试太多并最终破坏我的 View 模型之前做过类似的事情哈哈。

提前致谢。

[更新] - 这是我经过多次集思广益得出的解决方案(适用于任何其他希望做同样事情的人)。感谢 AnthonyWJones 提出的想法。

我所做的是将一个通用“模型”放在一起,它充当模型的源集合和“ View ”集合之间的桥梁。预期目的(对我而言)是扩展 WCF RIA 服务生成的任何模型类,这些模型类在使用相同的 UI(控件和模板)时可能具有与之关联的注释,因此预期的集合是一个 EntityCollection,其中 T 是 '实体'

Silverlight 客户端项目中声明了以下所有类

首先是一些管道:

// this is so we can reference our model without generic arguments
public interface ICommentModel : INotifyPropertyChanged
{
Int32 TotalComments { get; }
Int32 VisibleComments { get; }

Boolean IsExpanded { get; set; }
Boolean IsExpandable { get; }

ICommand ExpandCommand { get; }

IEnumerable Collection { get; }
}

// the command we'll use to expand our collection
public class ExpandCommand : ICommand
{
ICommentModel model;

public ExpandCommand(ICommentModel model) {
this.model = model;
this.model.PropertyChanged += ModelPropertyChanged;
}

public bool CanExecute(object parameter) {
return this.model.IsExpandable;
}

public void Execute(object parameter) {
this.model.IsExpanded = !this.model.IsExpanded;
}

private void ModelPropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "IsExpandable")
RaiseCanExecuteChanged();
}

private void RaiseCanExecuteChanged() {
var execute = CanExecuteChanged;
if (execute != null) execute(this, EventArgs.Empty);
}

public event EventHandler CanExecuteChanged;
}

// and finally.. the big guns
public class CommentModel<TEntity> : ICommentModel
where TEntity : Entity
{
Boolean isExpanded;

ICommand expandCommand;

IEnumerable<TEntity> source;
IEnumerable<TEntity> originalSource;


public Int32 TotalComments { get { return originalSource.Count(); } }

public Int32 VisibleComments { get { return source.Count(); } }

public Boolean IsExpanded {
get { return isExpanded; }
set { isExpanded = value; OnIsExpandedChanged(); }
}

public Boolean IsExpandable {
get { return (!IsExpanded && originalSource.Count() > 2); }
}

public ICommand ExpandCommand {
get { return expandCommand; }
}

public IEnumerable Collection { get { return source; } }


public CommentModel(EntityCollection<TEntity> source) {
expandCommand = new ExpandCommand(this);

source.EntityAdded += OriginalSourceChanged;
source.EntityRemoved += OriginalSourceChanged;

originalSource = source;
UpdateBoundCollection();
}


private void OnIsExpandedChanged() {
OnPropertyChanged("IsExpanded");
UpdateBoundCollection();
}

private void OriginalSourceChanged(object sender, EntityCollectionChangedEventArgs<TEntity> e) {
OnPropertyChanged("TotalComments");
UpdateBoundCollection();
}

private void UpdateBoundCollection() {
if (IsExpanded)
source = originalSource.OrderBy(s => PropertySorter(s));
else
source = originalSource.OrderByDescending(s => PropertySorter(s)).Take(2).OrderBy(s => PropertySorter(s));

OnPropertyChanged("IsExpandable");
OnPropertyChanged("VisibleComments");
OnPropertyChanged("Collection");
}

// I wasn't sure how to get instances Func<T,TRet> into this class
// without some dirty hacking, so I used some reflection to run "OrderBy" queries
// All entities in my DataModel have 'bigint' Id columns
private long PropertySorter(TEntity s) {
var props = from x in s.GetType().GetProperties()
where x.Name == "Id"
select x;

if (props.Count() > 0)
return (long)props.First().GetValue(s, null);

return 0;
}


protected virtual void OnPropertyChanged(string propName) {
var x = PropertyChanged;
if (x != null) x(this, new PropertyChangedEventArgs(propName));
}

public event PropertyChangedEventHandler PropertyChanged;
}

现在我们需要使用它。 WCF RIA 服务生成标记为部分的类(我不知道是否存在它不存在的情况,但从我所看到的情况来看它确实存在)。因此,我们将扩展它生成的实体类以包含我们的新模型。

// this must be inside the same namespace the classes are generated in
// generally this is <ProjectName>.Web
public partial class Timeline
{
ICommentModel model;

public ICommentModel CommentModel {
get {
if (model == null)
model = new CommentModel<TimelineComment>(Comments);

return model;
}
}
}

现在我们可以在绑定(bind)中引用评论模型,其中“Timeline”类是数据/绑定(bind)上下文。

例子:

<UserControl x:Class="Testing.Comments"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="291" d:DesignWidth="382">

<Border CornerRadius="2" BorderBrush="{StaticResource LineBrush}" BorderThickness="1">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>

<StackPanel Visibility="{Binding Path=CommentModel.IsExpandable, Converter={StaticResource BooleanToVisibility}}">
<HyperlinkButton
FontSize="10"
Command="{Binding Path=CommentModel.ExpandCommand}"
Background="{StaticResource BackBrush}">
<TextBlock>
<Run Text="View all"/>
<Run Text="{Binding Path=CommentModel.TotalComments}"/>
<Run Text="comments"/>
</TextBlock>
</HyperlinkButton>
<Rectangle Height="1" Margin="0,1,0,0" Fill="{StaticResource LineBrush}" VerticalAlignment="Bottom"/>
</StackPanel>

<ItemsControl
Grid.Row="1"
ItemsSource="{Binding Path=CommentModel.Collection}"
ItemTemplate="{StaticResource CommentTemplate}" />
</Grid>
</Border>
</UserControl>

最佳答案

这是您的 ViewModel 的工作。在内部你有一个完整的项目集合。但是,最初 ViewModel 应该公开一个 IEnumerable,它只会提供一些可用的内容。

ViewModel 还将公开一个名为“ListAll”的 ICommand 属性。执行此命令时,会将公开的 IEnumerable 替换为列出所有项目的命令。

现在这是一个简单的例子,像您已经在做的那样绑定(bind) ItemsControl 并添加绑定(bind)“ListAll”命令的“更多”按钮。

关于c# - 如何在 ItemsControl 中仅显示集合中的几个项目 - Silverlight,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7732277/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com