Limit the number of rows displayed in Items control

痴心易碎 提交于 2019-12-01 09:31:15

Let's say your ItemsSource is set to MyObservableCollection.

Well, what if you change your ItemsSource so that it is pointing a MyOneItemCollection instead?

Then, just use LINQ to do something like this:

using System.Linq;
MyOneItemCollection = MyObservableCollection.First();

or

using System.Linq;
MyOneItemCollection = MyObservableCollection.Single(item => item.Id = MyId);
Enny

You can use a IValueConverter for this:

public class ItemsLimiter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        int count;
        if (Int32.TryParse((string)parameter, out count))
        {
            return ((IEnumerable<object>)value).Take(count);
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return null;
    }
}

In XAML you can use it like this:

<ItemsControl ItemsSource="{x:Bind Data, Converter={StaticResource ItemsLimiter}, ConverterParameter=12}">

If you only ever need one item to display you can show the first item using a ContentControl instead with the same available templating options:

<ContentControl DataContext="{erm:Items FieldName}" Content="{Binding [0]}">
    <DataTemplate>
        <TextBlock Text="{Binding}" TextWrapping="Wrap" FontSize="14" VerticalAlignment="Center" FontWeight="Bold" />
    </DataTemplate>
</ContentControl>

Check out my PaginatedObservableCollection here http://jobijoy.blogspot.com/2008/12/paginated-observablecollection.html

This is a subclassed observableCollection which lets you bind to N items and make the UI display 'n' items when you set ItemsPerPage. In your case if you put 1 and can bind the next and previous also to some buttons as in my sample.

Hope this give you some idea.

You can implement a custom CollectionView that only provides n elements. I did something similar in my autocomplete textbox control implementation, check it out here:

A Reusable WPF Autocomplete TextBox

Scroll down to the header titled Limiting the Completions List see what I did there.

You can do this by creating a CollectionView that produces only a single item. This is quite simple: Just subclass CollectionView and override OnCollectionChanged to set a filter to filter out everything except the first item in the underlying collection:

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
  base.OnCollectionChanged(args);
  var first = SourceCollection.FirstOrDefault();
  Filter = (obj) => obj == first;
}

Now you need to insert this CollectionView into your ItemsSource. If erm:Items's ProvideValue produces the actual collection or a Binding with no Converter, you can just create your own MarkupExtension which either wraps it in your custom view or adds a Converter to do the wrapping. On the other hand, if erm:Items produces a Binding that already has a Converter or you can't rely on knowing what it produces, you should probably use a more general solution - I would suggest attached properties.

To use attached properties, your ItemsControl will be bound like this:

<ItemsControl
  my:SinglerCollectionViewCreator.ItemsSource="{erm:Items FieldName}"
  ... />

and the code in the SinglerCollectionViewCreator class would be:

public class SinglerCollectionViewCreator : DependencyObject
{
  public object GetItemsSource(...  // use "propa" snippet to fill this in
  public void SetItemsSource(....
  public static readonly DependencyProperty ItemsSourceProperty = ...
  {
    PropertyChangedCallback = (obj, e)
    {
      obj.SetValue(ItemsControl.ItemsSourceProperty,
        new SinglerCollectionView(e.NewValue));
    }
  }
}

The way this work is, whenever your new SinglerCollectionViewCreator.ItemsSource property is set on any object, the value is wrapped inside your SinglerCollectionView class and the ItemsControl.ItemsSource is set on the same object.

Is there a way to do this entirely in XAML, without writing code?

<ItemsControl Height="100"  ItemsSource="{erm:Items FieldName}" Grid.Row="1" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" TextWrapping="Wrap" FontSize="14" VerticalAlignment="Center" FontWeight="Bold" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>    
</ItemsControl>

I have the items source bound like above. The Items markup extension returns observable collection of strings and I have no control over the observable collection.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!