WP8 observablecollection项更新未反映在视图中

时间:2013-11-03 05:12:38

标签: c# xaml data-binding windows-phone-8 observablecollection

我有以下XAML来获取数据项列表:

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

模板定义如下:

<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>

在我的ViewModel中我有这个:

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");
    }

“TrulyObservableCollection&lt;&gt;”类来自this SO post

“PortfolioModel”类定义如下:

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));
        }
    }
}

“HoldModel”类定义如下:

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));
        }
    }
}

我想要做的是,每次我更新HoldModel中的CurrentPrice属性时,我都希望看到PortfolioModel中的NAV属性发生变化,并在视图中反映出来。我尽我所能,但仍然无法实现。有什么我想念的吗?任何帮助表示赞赏

2 个答案:

答案 0 :(得分:0)

我还注意到LongListSelector和ObservableCollection存在一些问题。我在这里贴了它:
Long List Selector Observable Collection and Visual Tree - problems?

请检查你的项目是这样的:留下带有后退按钮的页面并用LLS重新输入页面 - 如果它正确显示意味着我们有同样的问题,我认为这是LLS的问题我们有等待WP 8.1。我假设LLS没有正确更新(VisualTree不会改变),因为当我使用普通的ListBox时,一切都很完美。

尝试使用ListBox(因为您没有分组):

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

如果你没有看到更改,你可以尝试调用(在我的项目中,该函数没有使用LLS,但LisBox工作正常):

Port_SummaryList.UpdateLayout();

答案 1 :(得分:0)

尝试在NAV绑定中明确指定Mode=OneWay

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

我只是遇到Mode表现得像Mode=OneTime的默认情况。显式设置Mode=OneWay后,我的数据更改开始显示。 BindingMode枚举文档here暗示Mode=OneWay是隐含的。最近的经验表明情况可能并非总是如此。