我有以下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属性发生变化,并在视图中反映出来。我尽我所能,但仍然无法实现。有什么我想念的吗?任何帮助表示赞赏
答案 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
是隐含的。最近的经验表明情况可能并非总是如此。