0

I have the following XAML for a list of data items:

<phone:LongListSelector x:Name="Port_SummaryList" ItemsSource="{Binding PortList}" ItemTemplate="{StaticResource PortfolioDataTemplate}"/>   

The template is defined as this:

<phone:PhoneApplicationPage.Resources>
    <DataTemplate x:Key="PortfolioDataTemplate">
        <Grid d:DesignHeight="91.5" d:DesignWidth="439.875" Height="82">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="31*"/>
                <ColumnDefinition Width="19*"/>
                <ColumnDefinition Width="19*"/>
                <ColumnDefinition Width="19*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="15*"/>
                <RowDefinition Height="15*"/>
                <RowDefinition Height="15*"/>
            </Grid.RowDefinitions>
            <TextBlock x:Name="PortfolioName" HorizontalAlignment="Left" Height="92" TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Top" Width="155" Grid.RowSpan="2" Margin="0,0,0,-10"/>
            <TextBlock x:Name="NAV" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Height="31" TextWrapping="Wrap" Text="{Binding NAV, StringFormat='{}{0:C}'}" VerticalAlignment="Top" Width="95" Margin="0,-1,0,0"/>
            <TextBlock x:Name="CostBasis" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left" Height="30" TextWrapping="Wrap" Text="{Binding Cost,StringFormat='{}{0:C}'}" VerticalAlignment="Top" Width="95" />                               
        </Grid>
    </DataTemplate>
</phone:PhoneApplicationPage.Resources>

and in my ViewModel I have this:

private TrulyObservableCollection<PortfolioModel> _PortList;
    public TrulyObservableCollection<PortfolioModel> PortList
    {
        get { return _PortList; }
        set
        {
            _PortList = value;
            _PortList.CollectionChanged += _PortList_CollectionChanged;
            RaisePropertyChanged("PortList");
        }
    }

    void _PortList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        RaisePropertyChanged("PortList");
    }

The class "TrulyObservableCollection<>" is from this SO post.

The class "PortfolioModel" is defined as this:

public class PortfolioModel : INotifyPropertyChanged
{
    public string Name { get; set; }
    public DateTime Created { get; set; }
    public int Id { get; set; }

    public TrulyObservableCollection<CashModel> Cashflow;
    public TrulyObservableCollection<HoldingModel> Positions;

    public float Cost
    {
        get
        {
            float total_cost = 0.0f;
            foreach (HoldingModel holding in Positions)
            {
                total_cost += holding.Share * holding.CostBasis;
            }
            return total_cost;
        }
        private set { ;}
    }
    //Numbers that are calculated with other variables, listed here for databinding purposes
    public float NAV
    {
        get
        {
            float acc = 0.0f;
            foreach (HoldingModel hm in Positions)
            {
                acc += hm.CurrentPrice * hm.Share;
            }
            foreach (CashModel cm in Cashflow)
            {
                acc += cm.Amount;
            }
            return acc;
        }
        set { ;}
    }
    public float DailyPercent { get; set; }
    public float OverallPercent { get; set; }

    public PortfolioModel()
    {
        Cashflow = new TrulyObservableCollection<CashModel>();
        Cashflow.CollectionChanged += Cashflow_CollectionChanged;
        Positions = new TrulyObservableCollection<HoldingModel>();
        Positions.CollectionChanged += Positions_CollectionChanged;
    }

    void Positions_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        NotifyPropertyChanged("Positions");
        NotifyPropertyChanged("NAV");
    }        
    void Cashflow_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        NotifyPropertyChanged("Cashflow");
        NotifyPropertyChanged("NAV");
    }       


    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

The class "HoldingModel" is defined as this:

public class HoldingModel : INotifyPropertyChanged
{
    private string _Ticker;
    public string Ticker
    {
        get { return _Ticker; }
        set { if (value != _Ticker) { _Ticker = value; NotifyPropertyChanged("Ticker"); } }
    }

    private string _CompanyName;
    public string CompanyName
    {
        get { return _CompanyName; }
        set { if (value != _CompanyName) { _CompanyName = value; NotifyPropertyChanged("CompanyName"); } }
    }

    private int _Share;
    public int Share
    {
        get { return _Share; }
        set { if (value != _Share) { _Share = value; NotifyPropertyChanged("Share"); } }
    } //negative means short

    public string LongShort
    {
        get { if (Share > 0) return "LONG"; else return "SHORT"; }
    }

    private float _Value;
    public float Value
    {
        get { return _Value; }
        set { if (value != _Value) { _Value = value; NotifyPropertyChanged("Value"); } }
    }

    public float Cost
    {
        get { return Share * CostBasis; }
        set { ;}
    }

    private float _CostBasis;
    public float CostBasis
    {
        get { return _CostBasis; }
        set { if (value != _CostBasis) { _CostBasis = value; NotifyPropertyChanged("CostBasis"); } }
    }

    private float _RealizedGain;
    public float RealizedGain
    {
        get { return _RealizedGain; }
        set { _RealizedGain = value; NotifyPropertyChanged("RealizedGain"); }
    }

    private float _CurrentPrice;
    public float CurrentPrice
    {
        get { return _CurrentPrice; }
        set
        {
            _CurrentPrice = value;
            NotifyPropertyChanged("CurrentPrice");
        }
    }

    private float _CurrentChange;
    public float CurrentChange
    {
        get { return _CurrentChange; }
        set { _CurrentChange = value; NotifyPropertyChanged("CurrentChange"); }
    }

    ObservableCollection<TradeModel> Trades;

    public HoldingModel()
    {
        Trades = new ObservableCollection<TradeModel>();
    }

    public void AddTrade(TradeModel trade)
    {
        //Order can't change, since RealizedGain relies on CostBasis and Share, CostBasis relies on Share
        UpdateRealizedGain(trade);
        UpdateCostBasis(trade);
        Share += trade.Share;
        trade.PropertyChanged += PropertyChanged;
        Trades.Add(trade);
    }
    private void UpdateCostBasis(TradeModel trade)
    {
        if (trade.Share + Share == 0)
        {
            CostBasis = 0;
            return;
        }
        float cost = CostBasis * Share;
        cost += trade.Price * trade.Share;
        CostBasis = cost / (Share + trade.Share);
    }
    private void UpdateRealizedGain(TradeModel trade)
    {
        if (trade.Share * Share > 0) return; //No realized gain on add-on
        if (Math.Abs(trade.Share) > Math.Abs(Share))
        {
            RealizedGain += Share * (trade.Price - CostBasis);
        }
        else
        {
            RealizedGain += trade.Share * (trade.Price - CostBasis);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        //Debug.WriteLine("symbol_user got property {0} changed, bubbling up", propertyName);
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

What I wanted to do is that, every time I update the CurrentPrice property in HoldingModel, I want to see the NAV property in PortfolioModel change, and reflect that in the view. I tried all I can but still unable to achieve that. Is there anything that I'm missing? Any help is appreciated

Community
  • 1
  • 1
hxdai
  • 53
  • 1
  • 9

2 Answers2

0

I've also noticed some problems with LongListSelector and ObservableCollection. I've posted it here:
Long List Selector Observable Collection and Visual Tree - problems?

Please check in your project something like this: leave the Page with back button and the reenter the page with LLS - if it's correctly displayed that mean we have the same problems, and I think it's the problem with LLS and we have to wait for WP 8.1. I assume that LLS is not correctly Updated (VisualTree doesn't change), because when I use normal ListBox everything works perfect.

Try to use ListBox (as you don't have grouping):

<ListBox x:Name="Port_SummaryList" ItemsSource="{Binding PortList}" ItemTemplate="{StaticResource PortfolioDataTemplate}"/>

If you don't see changes you can try call (in my project that function didn't worj with LLS but with LisBox works fine):

Port_SummaryList.UpdateLayout();
Community
  • 1
  • 1
Romasz
  • 29,662
  • 13
  • 79
  • 154
0

Try explicitly specifying Mode=OneWay in the NAV binding.

Text="{Binding NAV, Mode=OneWay, StringFormat='{}{0:C}'}"

I just had a case where the Mode behaved like it was defaulting to the Mode=OneTime. After explicitly setting Mode=OneWay, my data changes started to display. The BindingMode Enumeration documentation here suggests Mode=OneWay is implied. Recent experience suggests that may not always be the case.

Gyle Iverson
  • 661
  • 1
  • 9
  • 17