2 Replies - 2199 Views - Last Post: 22 May 2014 - 04:30 PM

#1 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3511
  • View blog
  • Posts: 11,992
  • Joined: 12-December 12

WPF record x of y

Posted 13 May 2014 - 03:08 PM

This relates to the example application in my tutorial here.

I would like my StatusBar to display "Record 2 of 5". My collection is in the scope of a Grid-UserControl so my first attempt is to display on the Grid. (Later, I'll try and refer to it from the StatusBar.

Here is the relevant code from MyObservableCollection:
    public class MyObservableCollection<T> : ObservableCollection<T> {

        public MyObservableCollection() : base() {
        }

        private System.ComponentModel.ICollectionView GetDefaultView() {
            return System.Windows.Data.CollectionViewSource.GetDefaultView(this);
        }

        public int CurrentPosition {
            get {
                return this.GetDefaultView().CurrentPosition;
            }
        }

In the Grid's XAML I'm using this:
        <TextBlock Grid.Row="2" Grid.Column="3">
            <TextBlock Text="{Binding CurrentPosition}" /> <TextBlock Text="{Binding Count}" />
        </TextBlock>

This correctly displays, and automatically updates, the record-count, but constantly displays 0 for the record-number.

How can I get it to update automatically please? Hopefully, without using INotify.. because it is already an ObservableCollection.

(I have methods to change the current record so I could, I suppose, trigger some event from these methods but, again, I'm hoping to avoid this complication.)

Is This A Good Question/Topic? 0
  • +

Replies To: WPF record x of y

#2 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3511
  • View blog
  • Posts: 11,992
  • Joined: 12-December 12

Re: WPF record x of y

Posted 15 May 2014 - 04:40 PM

In the interest of full disclosure, I also posted my question here, but haven't had much of a response.

Anyway, I got my StatusBar to say "Item 2 of 5":
        <views:ToDo x:Name="vwToDo" DockPanel.Dock="Top" />
        <StatusBar DockPanel.Dock="Bottom">
            Item <TextBlock Text="{Binding ElementName=vwToDo, Path=DataContext.CurrentPosition}" />
            Of <TextBlock Text="{Binding ElementName=vwToDo, Path=DataContext.Count}" />
        </StatusBar>

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;

namespace ToDoApplication.Models {
    public class MyObservableCollection<T> : ObservableCollection<T>, INotifyPropertyChanged {
        public new event PropertyChangedEventHandler PropertyChanged;
        private int _currentPos = 1;

        public MyObservableCollection() : base() {
            this.GetDefaultView().CurrentChanged += MyObservableCollection_CurrentChanged;
            this.Collectionchanged += MyObservableCollection_Collectionchanged;
        }

        public MyObservableCollection(List<T> list) : base(list) {
            this.GetDefaultView().CurrentChanged += MyObservableCollection_CurrentChanged;
            this.Collectionchanged += MyObservableCollection_Collectionchanged;
        }
        public MyObservableCollection(IEnumerable<T> collection) : base(collection) {
            this.GetDefaultView().CurrentChanged += MyObservableCollection_CurrentChanged;
            this.Collectionchanged += MyObservableCollection_Collectionchanged;
        }

        void MyObservableCollection_CurrentChanged(object sender, EventArgs e) {
            this.CurrentPosition = this.GetDefaultView().CurrentPosition;
        }
        void MyObservableCollection_Collectionchanged(object sender, System.Collections.Specialized.NotifyCollectionchangedEventArgs e) {
            RaisePropertyChanged("Count");
        }

        private System.ComponentModel.ICollectionView GetDefaultView() {
            return System.Windows.Data.CollectionViewSource.GetDefaultView(this);
        }

        public int CurrentPosition {
            get {
                return _currentPos;
            }
            private set {
                if (_currentPos == value + 1) return;
                _currentPos = value + 1;
                RaisePropertyChanged("CurrentPosition");
            }
        }

        private void RaisePropertyChanged(string propertyName) {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public void MoveFirst() {
            this.GetDefaultView().MoveCurrentToFirst();
        }
        public void MovePrevious() {
            this.GetDefaultView().MoveCurrentToPrevious();
        }
        public void MoveNext() {
            this.GetDefaultView().MoveCurrentToNext();
        }
        public void MoveLast() {
            this.GetDefaultView().MoveCurrentToLast();
        }

        public bool CanMoveBack() {
            return this.CurrentPosition > 1;
        }
        public bool CanMoveForward() {
            return (this.Count > 0) && (this.CurrentPosition < this.Count);
        }
    }

    public enum Navigation {
        First, Previous, Next, Last, Add
    }
}


I had to use INotifyPropertyChanged. I would rather have not needed to do this, but I'm coming to terms with the idea that, because I'm adding a new property, it won't automatically be broadcast to any subscribers.

In the process of implementing INotifyPropertyChanged the Count property was no longer being updated automatically, and I've had to re-raise the event:
        void MyObservableCollection_Collectionchanged(object sender, System.Collections.Specialized.NotifyCollectionchangedEventArgs e) {
            RaisePropertyChanged("Count");
        }

Does anybody have any idea:
Why implementing INotifyPropertyChanged caused Count to no longer update automatically?
If I'm missing something and there is an easier way to re-instate this automatic feature? (Without having to re-notify of the change.)
Was This Post Helpful? 0
  • +
  • -

#3 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3511
  • View blog
  • Posts: 11,992
  • Joined: 12-December 12

Re: WPF record x of y

Posted 22 May 2014 - 04:30 PM

Answer:

Naming my property CurrentPosition is masking the property of the same name that is already available directly from the DataContext, because the binding is to the collection's default view (which has this property).

The solution is either to rename to MyCurrentPosition, and refer to the original property from the StatusBar or, as I did, to remove my version of this property (and of GetDefaultView) altogether: they aren't doing anything particularly useful.

I then use the following simple **ValueConverter** to convert 0,1,2,.. to 1,2,3,.. in the StatusBar.
    [ValueConversion(typeof(int), typeof(int))]
    class PositionConverter : IValueConverter {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
            return (int)value + 1;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
            return (int)value - 1;
        }
    }

StatusBar:
        <StatusBar DockPanel.Dock="Bottom" x:Name="status">
            Item <TextBlock Text="{Binding ElementName=vwToDo, 
                Path=DataContext.CurrentPosition, Converter={StaticResource posConverter}}" />
            Of <TextBlock Text="{Binding ElementName=vwToDo, Path=DataContext.Count}" />
        </StatusBar>

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1