Link to home
Start Free TrialLog in
Avatar of basil365
basil365Flag for Ireland

asked on

Data Template in wpf

Hi,

Im trying to create a custom control in wpf which will be used to display a list of custom objects

i have a list of these objects in my user control class called penalties.

the following code is on the xaml:

<ListBox ItemsSource="{Binding Penalties}" Grid.RowSpan="2" Grid.Row="2" Name="lstTest">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontWeight="Bold" Text="{Binding Team}" />
                        <TextBlock Text=" - " />
                        <TextBlock Text="{Binding TimeLeft}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

Open in new window


and the following is in the c#

private List<IceHockeyPenalty> penalties = null;

        public List<IceHockeyPenalty> Penalties
        {
            get { return penalties; }
            set { penalties = value; }
        }

        public PenaltyInfoControl()
        {
            InitializeComponent();
            this.penalties = new List<IceHockeyPenalty>();
            base.DataContext = penalties;
            lstTest.ItemsSource = penalties;
        }

        public void addPenaltyInfo(IceHockeyPenalty penaltyInfo)
        {
            penalties.Add(penaltyInfo);
        }

Open in new window


but nothing appears in the list when i add a new penalty

I've tried different variations of the above but no luck, can somebody tell me what i'm missing?

Thanks
SOLUTION
Avatar of Vaughn Bigham
Vaughn Bigham
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Try this.

private List<IceHockeyPenalty> penalties = null;

public PenaltyInfoControl()
{
  InitializeComponent();
  this.penalties = new List<IceHockeyPenalty>();
  this.DataContext = new { Penalties = penalties };
}

Open in new window


<ListBox ItemsSource="{Binding Penalties}" Grid.RowSpan="2" Grid.Row="2" Name="lstTest">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontWeight="Bold" Text="{Binding Team}" />
                        <TextBlock Text=" - " />
                        <TextBlock Text="{Binding TimeLeft}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox> 

Open in new window


Items in List<T> will be shown in the control once when the databinding happens. Any additions to the List<T> at run-time won't be reflected into the control. If your need is to add items to ListBox at run-time then as @vbigham mentioned you can change to ObservableCollection<T> instead of List<T>.
Avatar of basil365

ASKER

Thanks to you both, that works for the 'team' attribute on the icehockeypenalty object - it displays in the listbox correctly.

The 'timeLeft' attribute is slightly different in that in gets updated internally by a timer. The attribute itself is simply a string also, but no value gets printed on my data template.

this is the iceHockeyPenalty class:
public class IceHockeyPenalty
    {
        TimeSpan penaltyTime;
        DispatcherTimer timer;
        TimeSpan timerInterval = new TimeSpan(0, 0, 1);
        bool isValidPenalty;
        string team;
        string timeLeft;

        public string TimeLeft
        {
          get { return timeLeft; }
        }

        public string Team
        {
            get { return team; }
        }

        public IceHockeyPenalty(TimeSpan penaltyTime,string team)
        {
            this.team = team;
            this.penaltyTime = penaltyTime;
            timer = new DispatcherTimer();
            timer.Interval = timerInterval;
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
            isValidPenalty = true;
        }

        void timer_Tick(object sender, EventArgs e)
        {
            //reduce the penalty time left
            penaltyTime = penaltyTime.Subtract(timerInterval);

            //make sure this peno is not counted if its not valid
            if (penaltyTime <= new TimeSpan(0, 0, 0))
                isValidPenalty = false;

            timeLeft = penaltyTime.Minutes + ":" + penaltyTime.Seconds;
        }

        public void extendPenalty(int minutes)
        {
            this.penaltyTime.Add(new TimeSpan(0,minutes,0));
        }

    }

Open in new window

Did you changed to ObservableCollection?
I did, that seems to just update if the collection changes - not if the internal objects of that collection change?

I'm looking at IObserver<T> at the moment but its current out of my grasp
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thanks very much