none
commandhandlers stacking up inside itemscontrol after clear / re add

    Question

  • Hello all, I am having a little problem

    I have an itemscontrol bound to an ObservableCollection. In the itemscontrol's datatemplate, I bind a DatePickers SelectedDateChanged event to a command in the view model.

    The items in the itemscontrol get a certain look after what values their properties are, so when the properties of an items ObservableCollection are changed, I "refresh" the itemscontrol datatemplate by simply clearing the observablecollection and re adding the elements.

    The problem I have is that for each time I clear/readd the items, the command in my view model is called n-more times, where n is the number of times I "refresh".

    Obviously there are some objects / handlers left or stacking up.

    For binding to the SelectedDateChange command i use acb, http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/

    Can post some code tomorrow if needed. Thanks


    Edit

    <Window x:Class="EventBugging.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:Eventing="clr-namespace:KrediNor.Communicare.Common.Eventing" 
        xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation" 
        xmlns:Controls1="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" Title="Window1" 
        Height="800" 
        Width="500">
        <Grid x:Name="MyGrid">
            <StackPanel>
                <Button Content="Refresh" cal:Click.Command="{Binding RefreshCommand}" />
                <ItemsControl ItemsSource="{Binding People}" >
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Controls1:DatePicker 
                                    SelectedDate="{Binding Time, Mode=TwoWay}" >
                                    <Eventing:CommandBehaviorCollection.Behaviors>
                                        <Eventing:BehaviorBinding 
                                            Event="SelectedDateChanged" 
                                            Command="{Binding ElementName=MyGrid, Path=DataContext.DateChanged}"
                                            CommandParameter="{Binding }"
                                    />
                                    </Eventing:CommandBehaviorCollection.Behaviors>
                                </Controls1:DatePicker>
    
    
                                <TextBlock Text="{Binding Name}" />
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
    
                <TextBox Height="500" Text="{Binding Logg, Mode=TwoWay}" />
            </StackPanel>
        </Grid>
    </Window>
    
    namespace EventBugging
    {
        using System;
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.ComponentModel;
        using Microsoft.Practices.Composite.Presentation.Commands;
    
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : INotifyPropertyChanged
        {
            public DelegateCommand<object> DateChanged { get; set; }
            public DelegateCommand<object> RefreshCommand { get; set; }
            List<Person> _archive = new List<Person>();
    
            private ObservableCollection<Person> _people;
            public ObservableCollection<Person> People
            {
                get { return _people; }
                set
                {
                    _people = value;
                    NotifyPropertyChanged("People");
                }
            }
    
            private string _logg;
            public string Logg
            {
                get
                {
                    return _logg;
                }
                set
                {
                    _logg = value;
                    NotifyPropertyChanged("Logg");
                }
            }
    
            public Window1()
            {
                InitializeComponent();
                _archive = GetListOfPersons();
                _people = new ObservableCollection<Person>(_archive);
                DataContext = this;
                DateChanged = new DelegateCommand<object>(DateChangedCommandHandler);
                RefreshCommand = new DelegateCommand<object>(RefreshCommandHandler);
            }
    
            private void RefreshCommandHandler(object obj)
            {
                People = new ObservableCollection<Person>(_archive);
            }
    
            private void DateChangedCommandHandler(object obj)
            {
                var person = obj as Person;
                Logg += person.Name + "\n";
                RefreshCommandHandler(null);
            }
    
            static List<Person> GetListOfPersons()
            {
                var people = new List<Person>();
                people.Add(new Person("Luke", DateTime.Now));
                people.Add(new Person("Joe", DateTime.Now));
                people.Add(new Person("Williak", DateTime.Now));
                people.Add(new Person("Jack", DateTime.Now));
                people.Add(new Person("Averell", DateTime.Now));
                return people;
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            public void NotifyPropertyChanged(string propertyName)
            {
                if(PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    
        public class Person
        {
            public string Name { get; set; }
    
            private DateTime _time;
            public DateTime Time
            {
                get { return _time; }
                set { _time = value; }
            }
    
            public Person(string name, DateTime time)
            {
                Name = name;
                Time = time;
            }
        }
    }
    

    • Edited by BBuddy Friday, February 26, 2010 9:15 AM added code sample
    Thursday, February 25, 2010 9:01 PM

Answers

  • Hi BBuddy,

    I think the reason cause this problem is that you refresh the items with the reference itself. When you refresh the items with the following sentence:
    People = new ObservableCollection<Person>(_archive);
    it will get and set the property Time of people, while you have defined behaviors for it in XAML.

    If you change the way to refresh as follows, the problem will be solved:

    Code-behind(Modified part)

    private void RefreshCommandHandler(object obj)

    {

        People = new ObservableCollection<Person>(RefreshPeople());

    }

    private List<Person> RefreshPeople()

    {

        var people = new List<Person>();

        people.Add(new Person(_people[0].Name, _people[0].Time));

        people.Add(new Person(_people[1].Name, _people[1].Time));

        people.Add(new Person(_people[2].Name, _people[2].Time));

        people.Add(new Person(_people[3].Name, _people[3].Time));

        people.Add(new Person(_people[4].Name, _people[4].Time));

        return people;

    }

     

    Hope this helps.

    Best regards,
    Linda Liu


    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! If you have any feedback, please tell us.
    • Marked as answer by Linda Liu Thursday, March 04, 2010 3:19 AM
    Tuesday, March 02, 2010 12:32 PM