0

I'm new to WPF and having some trouble with ListView's. I've created a list view to visually display data in an Observable collection to users. The only problem is the ListView doesn't update when values within the ObservableCollection are changed. If an element is added or removed that is displayed correctly, however. Closing and reopening the window will also cause it to display the correct data.

The xaml for the list view window is

<Grid>
    <ListView Name="RunningCycleListView" HorizontalAlignment="Left" Height="266" VerticalAlignment="Top" Width="546" ItemsSource="{Binding RunningCycles, BindsDirectlyToSource=True}">
        <ListView.Resources>
            <Style TargetType="{x:Type ListViewItem}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding OverCycleLogged}" Value="true">
                        <Setter Property="Background" Value="Red"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListView.Resources>
        <ListView.View>
            <GridView>
                <GridViewColumn DisplayMemberBinding="{Binding Name}">
                    <GridViewColumnHeader Width="100">
                        <TextBlock Text="Cycle Name"/>
                    </GridViewColumnHeader>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding AGV.AgvGroup}">
                    <GridViewColumnHeader Width="67">
                        <TextBlock Text="Group"/>
                    </GridViewColumnHeader>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding AGV.Type}">
                    <GridViewColumnHeader Width="67">
                        <TextBlock Text="Type"/>
                    </GridViewColumnHeader>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding AGV.AgvID_Number}" Width="90">
                    <GridViewColumnHeader Width="90">
                        <TextBlock Text="ID"/>
                    </GridViewColumnHeader>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding StartTime}" Width="140">
                    <GridViewColumnHeader Width="140">
                        <TextBlock Text="Start Time"/>
                    </GridViewColumnHeader>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding MaxTime}">
                    <GridViewColumnHeader Width="75">
                        <TextBlock Text="Max Time"/>
                    </GridViewColumnHeader>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

The c# associated with that is simple

    public partial class CycleViewerWindow : Window
{
    public CycleViewerVM viewModel;

    public CycleViewerWindow(ObservableCollection<CycleTimer> runningCycles)
    {
        this.viewModel = new CycleViewerVM(runningCycles);
        InitializeComponent();
        this.DataContext = viewModel;
        this.Closing += CycleViewerWindow_Closing;
    }

    void CycleViewerWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        this.Closing -= CycleViewerWindow_Closing;
    }

And finally the view model...

public class CycleViewerVM
{
    public CycleViewerVM(ObservableCollection<CycleTimer> runningCycles)
    {
        this.RunningCycles = runningCycles;
    }
    private ObservableCollection<CycleTimer> runningCycles;
    public ObservableCollection<CycleTimer> RunningCycles
    {
        get { return runningCycles; }
        set { this.runningCycles = value; }
    }
}

I believe the ListView is bound to the ObservableCollection correctly, but can't seem to find whats wrong or a suitable work around.

CycleTimer class:

public class CycleTimer
{
    #region Constructor(s)

    public CycleTimer(string cycleTimerName, int CycleTimerStartRfid, int CycleTimerStopRfid, int CycleTimerMaxCount, AGVData agv = null)
    {
        this.name = cycleTimerName;
        this.cycleStartRfid = CycleTimerStartRfid;
        this.cycleStopRfid = CycleTimerStopRfid;
        this.maxTime = CycleTimerMaxCount;
        this.agv = agv;
        this.startTime = DateTime.Now;
    }

    #endregion Constructor(s)

    #region Fields and Properties

    private string name;
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    private DateTime startTime;
    public DateTime StartTime
    {
        get { return startTime; }
        protected set { startTime = value; }
    }

    private int maxTime;
    public int MaxTime
    {
        get { return maxTime; }
        set { maxTime = value; }
    }
    private AGVData agv;
    public AGVData AGV
    {
        get { return agv; }
    }


    private Boolean overCycleLogged;
    public Boolean OverCycleLogged
    {
        get { return this.overCycleLogged; }
        set { this.overCycleLogged = value; }
    }
    #endregion Fields and Properties

    #region Methods

    public Boolean isOverCycle()
    {
        DateTime maximumTime = this.startTime.AddSeconds(this.maxTime);
        if (DateTime.Now > maximumTime)
        {
            return true;
        }
        return false;
    }
    #endregion Methods
JShell
  • 624
  • 2
  • 7
  • 22
  • 6
    The ObservableCollection will show changes to the collection (add/remove). Changes to the properties of the items in the collection are governed by implementing INotifyPropertyChanged on the item class (CycleTimer) - if you share that class code, I can help further. – Mark W Jul 24 '15 at 17:18
  • try this.DataContext = viewModel.RunningCycles; – jsanalytics Jul 24 '15 at 17:18
  • Set the ItemsSource for the ListView. See http://stackoverflow.com/questions/10659347/bind-an-observablecollection-to-a-listview – iheanyi Jul 24 '15 at 17:24
  • 1
    @iheanyi is that not what ive done in the second line of the xaml? – JShell Jul 24 '15 at 17:36
  • @MarkW Question Edited – JShell Jul 24 '15 at 17:43
  • @iheanyi the question is not related to ItemSource please read the question properly and try to comment. – Abin Jul 25 '15 at 17:35
  • @AbinMathew No need to try, my comment posted successfully. – iheanyi Jul 27 '15 at 15:24
  • @iheanyi so you mean to say that its working because the ListView handles it. ok then why dont he tried using a List insted of ObservableCollection. if ListView handles the updating then what is the point of ObservableCollection? – Abin Jul 27 '15 at 15:30
  • @iheanyi Your link says how to bind ListView with an ObservableCollection. not the answer to the question posted above. – Abin Jul 27 '15 at 15:35

2 Answers2

2

Impliment INotifyPropertyChanged Interface with your model CycleTimer to get the changes get affected.

"Mark W" have already commented on this.

https://stackoverflow.com/a/1316417/2470362

ObservableCollection Class

Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.

so it wont notify when you change the model property.

Community
  • 1
  • 1
Abin
  • 2,868
  • 1
  • 23
  • 59
  • Yep... this is what I was referring to. I have not implemented it using the syntax referenced in that link (still on .Net 4.0), but that is the way to go to get the notification working. Thanks for following up, Abin. – Mark W Jul 24 '15 at 20:32
  • @MarkW Happy to help. – Abin Jul 24 '15 at 20:44
  • I don't think that needs to be implemented. That should be handled by the ListView. – iheanyi Jul 24 '15 at 22:40
  • @iheanyi if its handled by ListView why its not updating ? if you are sure about that give a sample which is working. – Abin Jul 25 '15 at 17:32
  • @AbinMathew See the link in my comment. – iheanyi Jul 27 '15 at 15:24
  • @iheanyi, The question is about " ListView doesn't update when values within the ObservableCollection are changed" for this one you need to impliment INotifyPropertyChanged interface and update it. or he can impliment Dependency Property to notify property change. – Abin Jul 27 '15 at 15:39
-1

I had an ObservableCollection of objects as a sub property.. which does the same as you complain.. even though implementing INotifyPropertyChanged>>

Solved by just this :

Obj.ObsCol = new ObservableCollection<Obj.ObsCol>
vimuth
  • 5,064
  • 33
  • 79
  • 116
Mohamed RT
  • 165
  • 2
  • 7