0

I'm designing an MVVM WPF app, and one of the controls is like this,

<ListView Grid.Row="5"  Margin="0,5,0,0" ItemsSource="{Binding temps, Mode=TwoWay}"/>

In the ViewModel, I have

public class IndicatorLightVM:DependencyObject
{
/*---*/
    public List<DataDev> temps { get; set;}
/*---*/

    public IndicatorLightVM(IComm icomm, int moduleAddr = 1)
    {
        iComm = icomm;
        pdm = new IndicatorLight(icomm, moduleAddr);
        temps = pdm.DataDevs;
    }

DataDevs has a list of DataDev as an attribute and DataDev is

public abstract class DataDev: INotifyPropertyChanged
{
    public int ModuleAddr { get; set; }
    private double _value;
    public double Value {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
            OnPropertyChanged("Value");
        }
    }
/*---*/
}

Then I call a method updating the Value of Datadev. When I tracked into the code, Values are changed but the UI is not updating.

public override CommResults ReadData()
    {
        channelselect = DataDevs.Count(d => d.isTest);
        byte[] recvbuf = new byte[channelselect * 2+7];
        byte[] sendbuf = new byte[7];
        sendbuf[0] = Convert.ToByte(ModuleAddr % 256);
        sendbuf[1] = 0X07;
        sendbuf[2] = 0X07;
        sendbuf[3] = BoolsToBytes()[0];
        sendbuf[4] = 0X00;

        CommResults result = GetCommData(sendbuf, recvbuf, channelselect * 2+7);
        if (result != CommResults.OK)
        {
            return result;
        }          
        AnalyseData(recvbuf);
        return CommResults.OK;
    }

    private void AnalyseData(byte[] recvbuf)
    {
        for (int i = 0; i < channelselect; i++)
        {
            byte ss = Convert.ToByte(recvbuf[i * 2 + 6] & 0xF8);
            if (Convert.ToInt32(ss) == 0xF8)
            {
                DataDevs.Where(x=>x.isTest).ToArray()[i].Value = (-((256 - recvbuf[i * 2 + 6]) * 256 - recvbuf[i * 2 + 5]) * 0.0625);
            }
            else if (Convert.ToInt32(ss) == 0)
            {
                DataDevs.Where(x => x.isTest).ToArray()[i].Value = ((recvbuf[i * 2 + 6] & 7) * 256 + recvbuf[i * 2 + 5]) * 0.0625;
            }
        }
    }

Sorry for missing code.

5
  • Then I call a method updating the Value of Datadev. Where is it ? Please add the code to your question. Commented Sep 4, 2017 at 6:00
  • Why does your "View-Model" derive from DependencyObject ? You should rather derive from an abstract base class which implements INotifyPropertyChanged. You might also want to add a notifier for your list, in case you exchange it with another list object. Commented Sep 4, 2017 at 6:09
  • How does the UI access the Value property. I don't see DisplayMemberPath, so I don't know whether you just have a ToString override in your /*---*/ part of code... Commented Sep 4, 2017 at 6:11
  • 1
    It would be better if you create a MCVE. There are a lot of details missing. Commented Sep 4, 2017 at 6:13
  • @grek40 yes, I override ToString Commented Sep 4, 2017 at 6:22

2 Answers 2

4

The problem is you don't directly use the Value in your UI.

Solution:

<ListView
    Grid.Row="5"
    Margin="0,5,0,0"
    ItemsSource="{Binding temps, Mode=TwoWay}"
    DisplayMemberPath="Value"/>

Your current approach goes the following route:

Value -> ToString -> GUI

So the GUI doesn't know it has to update on Value change. WPF will only react to property change notifications when it is aware of the property being used in the GUI and that doesn't work via ToString but only with ...Path="PropertyName" or with Bindings targeting the property.

Sign up to request clarification or add additional context in comments.

1 Comment

Gods! Thank you! I've been stuck for a day. Thanks so much!
-1

Change the type of the List to an ObservableCollection.

public class IndicatorLightVM:DependencyObject
{
    /*---*/
    public ObservableCollection<DataDev> temps { get; set;}
    /*---*/
}

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

Update

You need a "custom" ObservableCollection. This question is a possible duplicate of this SO answer. To get there you still need and ObservableCollection. By implementing the answer there you'll solve your issue.

4 Comments

He's not adding or removing an element. He's modifying the content of an element which already has a notifier.
I've tried ObservableCollection, still not working. I thought ObservableCollection is used when you removing/adding elements from/to a list. Yeah, I'm doing what Blacktempel said.
At least the accepted answer in the linked SO question doesn't really address the issue of this question. So if you think its a duplicate, you should mention which answer would specifically be the solution.
You are correct @grek40, thank you for pointing it out. The answer that would help this question is the second one. Because that answer provides the way to update all the bindings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.