Stellen Sie eine FrageStellen Sie eine Frage
 

BeantwortetPaging ListBox

  • Mittwoch, 28. Oktober 2009 20:29ykab TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     

    Hello,
    I have a ListBox with its ItemsTemplate set to a DataTemplate with known dimensions.
    The DataTemplate presents my Product class, a list of which is the ListBox's ItemsSource.
    I have modified the scrollbar template to override the commands for the up/down buttons
    to ScrollBar.PageUpCommand and ScrollBar.PageDownCommand respectively, the aim
    being to display items by page, fixed item count per page. I have taken care to size
    the ListBox accordingly. Problem is, let's say I have 10 items per page and a total of
    17 items. I want to show the first 10 in the first page and items 11-17 in the second
    page with empty space at the bottom. The default behaviour of the ListBox is to display
    the last 10 items, 7 to 17. I thought about padding the listbox with 3 invisible items
    by using a trigger in the DataTemplate that gets activated by a property in my Product
    business object (isPadding), and adding extra dummy items at the end of the list.
    But it's not the Product's responsibility to make my ListBox show like it should, and it
    causes side effects with other parts of my code adding these extra items at the end.
    Is there a way I can resolve this in a similar or completely different fashion?

    Thanks.

Antworten

  • Mittwoch, 4. November 2009 17:32Zhi-Xin YeMSFT, ModeratorTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet
    Hi ykab,

    It's better to page on the data source. A possible solution is use the CollectionViewSource object, we can use its Filter event to filter the data, and only display the page of data that needed. See my sample below for the details:

        <Grid>
            <ListBox Margin="20,19,12,60" Name="listBox1" ItemsSource="{Binding}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding ID}"/>
                            <TextBlock Text="{Binding Name}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <Button Height="23" HorizontalAlignment="Left" Margin="20,0,0,23" Name="button1" VerticalAlignment="Bottom" Width="75" Click="button1_Click">Button</Button>
            <Button Height="23" HorizontalAlignment="Left" Margin="109,0,0,23" Name="button2" VerticalAlignment="Bottom" Width="75" Click="button2_Click">Button</Button>
            <Button Height="23" Margin="206,0,0,23" Name="button3" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="75" Click="button3_Click">Button</Button>
            <Button Height="23" HorizontalAlignment="Right" Margin="0,0,191,23" Name="button4" VerticalAlignment="Bottom" Width="75" Click="button4_Click">Button</Button>
        </Grid>


     public partial class Paging : Window
        {
            public Paging()
            {
                InitializeComponent();

                Loaded += new RoutedEventHandler(Paging_Loaded);
            }

            void Paging_Loaded(object sender, RoutedEventArgs e)
            {
                int itemcount = 107;
                for (int j = 0; j < itemcount; j++)
                {
                    objs.Add(new MyOjbect() { ID = j, Name = "item" + j.ToString() });
                }
               
                // Calculate the total pages
                totalPage = itemcount / itemPerPage;
                if (itemcount % itemPerPage != 0)
                    totalPage += 1;

                view.Source = objs;
               
                // To display the last page by default.
                currentPageIndex = totalPage - 1;

               
                view.Filter += new FilterEventHandler(view_Filter);

                listBox1.DataContext = view;
            }

            void view_Filter (object sender, FilterEventArgs e)
            {
                int index = objs.IndexOf((MyOjbect)e.Item);
                if (index >= itemPerPage * currentPageIndex && index < itemPerPage * (currentPageIndex + 1))
                {
                    e.Accepted = true;
                }
                else
                {
                    e.Accepted = false;
                }

            }

            CollectionViewSource view = new CollectionViewSource();
            ObservableCollection<MyOjbect> objs = new ObservableCollection<MyOjbect>();
            int currentPageIndex = 0;
            int itemPerPage = 20;
            int totalPage = 0;

            private void button1_Click(object sender, RoutedEventArgs e)
            {
                 // Display next page
                if (currentPageIndex < totalPage-1)
                {
                    currentPageIndex++;
                    view.View.Refresh();
                }
            }

            private void button2_Click(object sender, RoutedEventArgs e)
            {
                // Display previous page
                if (currentPageIndex > 0)
                {
                    currentPageIndex--;
                    view.View.Refresh();
                }
            }

            private void button3_Click(object sender, RoutedEventArgs e)
            {
                 // Display the first page
                if (currentPageIndex != 0 )
                {
                    currentPageIndex = 0;
                    view.View.Refresh();
                }
            }

            private void button4_Click(object sender, RoutedEventArgs e)
            {
                // Display the last page
                if (currentPageIndex != totalPage-1)
                {
                    currentPageIndex = totalPage-1;
                    view.View.Refresh();
                }
            }
        }

        public class MyOjbect
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }


    If anything is unclear, please feel free to let me know.

    Best Regards,
    Zhi-Xin Ye


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework!

Alle Antworten

  • Mittwoch, 4. November 2009 17:32Zhi-Xin YeMSFT, ModeratorTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet
    Hi ykab,

    It's better to page on the data source. A possible solution is use the CollectionViewSource object, we can use its Filter event to filter the data, and only display the page of data that needed. See my sample below for the details:

        <Grid>
            <ListBox Margin="20,19,12,60" Name="listBox1" ItemsSource="{Binding}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding ID}"/>
                            <TextBlock Text="{Binding Name}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <Button Height="23" HorizontalAlignment="Left" Margin="20,0,0,23" Name="button1" VerticalAlignment="Bottom" Width="75" Click="button1_Click">Button</Button>
            <Button Height="23" HorizontalAlignment="Left" Margin="109,0,0,23" Name="button2" VerticalAlignment="Bottom" Width="75" Click="button2_Click">Button</Button>
            <Button Height="23" Margin="206,0,0,23" Name="button3" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="75" Click="button3_Click">Button</Button>
            <Button Height="23" HorizontalAlignment="Right" Margin="0,0,191,23" Name="button4" VerticalAlignment="Bottom" Width="75" Click="button4_Click">Button</Button>
        </Grid>


     public partial class Paging : Window
        {
            public Paging()
            {
                InitializeComponent();

                Loaded += new RoutedEventHandler(Paging_Loaded);
            }

            void Paging_Loaded(object sender, RoutedEventArgs e)
            {
                int itemcount = 107;
                for (int j = 0; j < itemcount; j++)
                {
                    objs.Add(new MyOjbect() { ID = j, Name = "item" + j.ToString() });
                }
               
                // Calculate the total pages
                totalPage = itemcount / itemPerPage;
                if (itemcount % itemPerPage != 0)
                    totalPage += 1;

                view.Source = objs;
               
                // To display the last page by default.
                currentPageIndex = totalPage - 1;

               
                view.Filter += new FilterEventHandler(view_Filter);

                listBox1.DataContext = view;
            }

            void view_Filter (object sender, FilterEventArgs e)
            {
                int index = objs.IndexOf((MyOjbect)e.Item);
                if (index >= itemPerPage * currentPageIndex && index < itemPerPage * (currentPageIndex + 1))
                {
                    e.Accepted = true;
                }
                else
                {
                    e.Accepted = false;
                }

            }

            CollectionViewSource view = new CollectionViewSource();
            ObservableCollection<MyOjbect> objs = new ObservableCollection<MyOjbect>();
            int currentPageIndex = 0;
            int itemPerPage = 20;
            int totalPage = 0;

            private void button1_Click(object sender, RoutedEventArgs e)
            {
                 // Display next page
                if (currentPageIndex < totalPage-1)
                {
                    currentPageIndex++;
                    view.View.Refresh();
                }
            }

            private void button2_Click(object sender, RoutedEventArgs e)
            {
                // Display previous page
                if (currentPageIndex > 0)
                {
                    currentPageIndex--;
                    view.View.Refresh();
                }
            }

            private void button3_Click(object sender, RoutedEventArgs e)
            {
                 // Display the first page
                if (currentPageIndex != 0 )
                {
                    currentPageIndex = 0;
                    view.View.Refresh();
                }
            }

            private void button4_Click(object sender, RoutedEventArgs e)
            {
                // Display the last page
                if (currentPageIndex != totalPage-1)
                {
                    currentPageIndex = totalPage-1;
                    view.View.Refresh();
                }
            }
        }

        public class MyOjbect
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }


    If anything is unclear, please feel free to let me know.

    Best Regards,
    Zhi-Xin Ye


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework!