3
votes

I'm having some trouble getting a binding to work that is defined in the resouces section of my user control. The same binding seems to work later on in the xaml when I bind it to a column of the datagrid. It just won't display data when in the style declaration.

The error I get is

System.Windows.Data Error: 40 : BindingExpression path error: 'ReceivedDate' property not found on 'object' ''CollectionViewGroupInternal' (HashCode=5477078)'. BindingExpression:Path=ReceivedDate; DataItem='CollectionViewGroupInternal' (HashCode=5477078); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

The below binding ReceivedDate is not resolving at runtime.

<UserControl.Resources>

    <!-- Grouped Items Header: Show the messages in a group. ex: date received -->
    <Style x:Key="GroupedItemsHeaderStyle" TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type GroupItem}">
                    <Expander x:Name="exp" IsExpanded="True"
                              Background="LightGray"
                              Foreground="Black">
                        <Expander.Header>
                            <TextBlock Text="{Binding Path=ReceivedDate, Converter={StaticResource DateToSortGroupConverter}}" Foreground="Black"/>
                        </Expander.Header>
                        <ItemsPresenter/>
                    </Expander>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</UserControl.Resources>

In the code-behind for this UserControl I'm setting the itemsList as follows.

    void MailController_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "CurrentMailBoxContent")
        {
            var currentMailBox = ((App) Application.Current).MailController.CurrentMailBoxContent;
            var collection = new ListCollectionView(currentMailBox);

            collection.GroupDescriptions.Add(new PropertyGroupDescription("ReceivedDate"));
            ContentDataGrid.ItemsSource = collection;
        }
    }

CurrentMailBoxContent is an

ObservableCollection<MailMessage>;

and ReceivedDate is a property in the MailMessage class.

public class MailMessage : INotifyPropertyChanged
{
    #region Fields

    public event PropertyChangedEventHandler PropertyChanged;

    private DateTime _receivedDate;

    #endregion

    #region Constructor

    public MailMessage(){}

    #endregion

    #region Properties


    public DateTime ReceivedDate
    {
        get { return _receivedDate; }
        set
        {
            if (_receivedDate == value) return;
            _receivedDate = value;
            OnPropertyChanged("ReceivedDate");
        }
    }

    #endregion

    #region methods

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

I've tried changing the path of the binding to /ReceivedDate.

The thing that confuses me is that the same binding works when declared elsewhere. Such as in the various column headers.

1
The Expander.Header does not get one of your view models. Instead the header gets its own object that has 2 properties named Name and ItemCount. That is in fact some sort of limitation of the cool grouping Feature.gomi42
Unbelievable. The example I followed used name and I didn't clue in because name was also the name of the property in that examples data model. Thank you gomi42. Please post your comment as an answer so I can give you credit.Redshirt

1 Answers

8
votes

The Expander.Header does not get one of your view models. Instead the header gets an object that inherits from CollectionViewGroup that has two properties named Name and ItemCount.