James
James

Reputation: 356

Databound list box not updating to correct values from observable collection WPF

I am new to WPF so could be something very simple I've missed.

I have a list box which is holding databound Class properties from a static observableCollection<myClass>. The collection is being updated several times a second from a network stream source and from what I can tell from debugging, the collection is being updated properly. The declaration is as follows: static ObservableCollection<PumpItem> pumpCollection = new ObservableCollection<PumpItem>(); where PumpItem is the name of my class.

That is not to say that the listbox isn't displaying anything however, it is updating to display any new values added to the collection but these only ever reflect the properties of the first moment they enter the collection.

The values of the listbox are bound as such:

 <ListBox x:Name="pumpListBox" ItemsSource="{Binding PumpCollection}" Grid.IsSharedSizeScope="True" Margin="0,0,153,0">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="ID" />
                        <ColumnDefinition SharedSizeGroup="State" />
                        <ColumnDefinition SharedSizeGroup="Selection" />
                        <ColumnDefinition SharedSizeGroup="Fuel Pumped" />
                        <ColumnDefinition SharedSizeGroup="Cost" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Margin="2" Text="{Binding PumpID}" Grid.Column="0"/>
                    <TextBlock Margin="2" Text="{Binding State}" Grid.Column="1"/>
                    <TextBlock Margin="2" Text="{Binding Selection}" Grid.Column="2"/>
                    <TextBlock Margin="2" Text="{Binding FuelPumped}" Grid.Column="3"/>
                    <TextBlock Margin="2" Text="{Binding FuelCost}" Grid.Column="4"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

I have this declaration in the code behind in order to set resources to the collection:

public static ObservableCollection<PumpItem> PumpCollection
        {
            get { return pumpCollection; }

        }

In my `MainWindow() constructor I've set:

this.DataContext = this;

before InitialiseComponent(); and my background worker thread to receive network inputs to update the list:worker.RunWorkerAsync();`

This background thread then loops continuously updates the collection from the stream and invokes a resource update:

 private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //background tasks
        Thread.Sleep(500); //allows the ui time to update and initialise
        string s_decryptedMessage = string.Empty;

        App.Current.Dispatcher.Invoke((Action)(() =>
        {
            Resources["PumpCollection"] = pumpCollection;

        }));


        while (true)
        {

            byteMessage = Recieve(stream);//get the number of pumps about to be recieved
            Interact(byteMessage); //signal server to update pumplist

        }
}

If it helps, my class code is thus:

namespace PoSClientWPF

{ public enum pumpState { Available, Waiting, Pumping, Paying };

public enum fuelSelection
{
    Petrol,
    Diesel,
    LPG,
    Hydrogen,
    None

};
public class PumpItem
{
    private string pumpID;
    public string PumpID
    {
        get
        {
            return pumpID;
        }
        set
        {
            pumpID = value;
        }
    }

    private double fuelPumped;
    public double FuelPumped
    {
        get
        {
            return fuelPumped;
        }
        set
        {
            fuelPumped = value;
        }
    }

    private double fuelCost;
    public double FuelCost
    {
        get
        {

            return fuelCost;
        }
        set
        {

            fuelCost = Math.Round(value, 2); //cost to two DP
        }
    }

    private fuelSelection selection;
    public fuelSelection Selection
    {
        get
        {
            return selection;
        }
        set
        {
            selection = value;
        }
    }

    private pumpState state;
    public pumpState State
    {
        get
        {
            return state;
        }
        set
        {
            state = value;
        }
    }

    public PumpItem(string _ID, pumpState _state, fuelSelection _selection)
    {
        this.pumpID = _ID;
        this.FuelPumped = 0;
        this.FuelCost = 0;
        this.Selection = _selection; 
        this.State = _state;
    }
}

}

As I said, I'm very new to WPF so would greatly appreciate any guidance or solutions. Thanks.

Upvotes: 0

Views: 44

Answers (1)

Matt Wilkinson
Matt Wilkinson

Reputation: 590

Ash was completely correct but here is a quick example for you to skim. This is and example of aViewModelBase which typically all ViewModels inherit from. From one of my repos. This how you would call your OnChangedEvent.

private sample _Item;
    public sample Item
    {
        get
        {
            return _Item;
        }
        set
        {
            if (_Item != value)
            {
                _Item = value;
                OnPropertyChanged("Item");
            }
        }
    }

This will get it where you update everything when properties change.

Upvotes: 1

Related Questions