【问题标题】:WP8 observablecollection item updates not reflected in viewWP8 observablecollection 项目更新未反映在视图中
【发布时间】:2013-11-03 05:12:37
【问题描述】:

我有以下 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”来自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));
        }
    }
}

“HoldingModel”类定义如下:

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

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

【问题讨论】:

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


    【解决方案1】:

    我还注意到 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();
    

    【讨论】:

      【解决方案2】:

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

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

      我刚刚遇到一个案例,Mode 的行为就像默认为 Mode=OneTime。在明确设置Mode=OneWay 后,我的数据更改开始显示。 BindingMode 枚举文档here 暗示Mode=OneWay 是隐含的。最近的经验表明,情况可能并非总是如此。

      【讨论】:

        猜你喜欢
        • 2010-11-24
        • 1970-01-01
        • 2021-04-19
        • 2011-07-02
        • 1970-01-01
        • 2014-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多