我有一个ListView
我正在使用RelayCommand
按钮点击更新。如果我在ListView
的构造函数中向observableCollection
添加项目,则ViewModel
会更新,但如果我在单击按钮后在方法中执行此操作,则会更新ObservableCollection
。
我花了很多时间研究StackOverflow,虽然有很多相关的问题我找不到答案。什么在困扰我,我无法理解的是,当我在构造函数中添加值时它会起作用。
我正在使用DataContext
将ObservableCollection
设置为在页面级别查看模型
在XAML中将ListView
绑定到<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyFare"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ViewModel="using:MyFare.ViewModel"
x:Class="MyFare.MainPage"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Main, Mode=OneWay, Source={StaticResource Locator}}">
<Grid Height="640" Margin="0,0.333,0,-0.333" VerticalAlignment="Top">
<TextBlock x:Name="title" Text="View My Fare" Margin="0,10,0,603"/>
<TextBox x:Name="txtCurrentValue" InputScope="Number" PlaceholderText="Enter your Current Balance" Margin="0,53,0,0" Text="{Binding CurrentBalance, Mode=TwoWay}"/>
<Button Content="Show Fares" HorizontalAlignment="Left" Margin="96,113,0,0" VerticalAlignment="Top" Command="{Binding ShowFaresCommand, Mode=OneWay}" CommandParameter="{Binding CurrentBalance}" />
<ListView x:Name="nbc" SelectionMode="Single" Margin="10,182,10,150" ItemsSource="{Binding Charges}">
<ListView.Resources>
<DataTemplate x:Key="FareTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding AmountToRecharge}" TextAlignment="Right" Grid.ColumnSpan="4" Margin="0,0,-28,0" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource TextStyleLargeFontSize}"></TextBlock>
<TextBlock Text="{Binding BonusAmount}" TextAlignment="Right" Margin="118.333,0,-128.333,0" Grid.Column="3" FontSize="{StaticResource TextStyleLargeFontSize}"/>
<TextBlock Text="{Binding NewBalance}" TextAlignment="Right" Margin="118,0,-229.333,0" Grid.Column="3" FontSize="{StaticResource TextStyleLargeFontSize}"/>
<TextBlock Text="{Binding NumberofRides}" TextAlignment="Right" Margin="298,0,-308.333,0" Grid.Column="3" FontSize="{StaticResource TextStyleLargeFontSize}"/>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="FaresPanelTemplate">
<VirtualizingStackPanel Orientation="Vertical"></VirtualizingStackPanel>
</ItemsPanelTemplate>
<DataTemplate x:Key="headerTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="Amount to Recharge" Grid.Column="0" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/>
<TextBlock Text="Bonus Amount" Grid.Column="1" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/>
<TextBlock Text="New Balance" Grid.Column="2" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/>
<TextBlock Text="Number of Rides" Grid.Column="3" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/>
</Grid>
</DataTemplate>
</ListView.Resources>
<ListView.HeaderTemplate>
<StaticResource ResourceKey="headerTemplate"/>
</ListView.HeaderTemplate>
<ListView.ItemsPanel>
<StaticResource ResourceKey="FaresPanelTemplate"/>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<StaticResource ResourceKey="FareTemplate"/>
</ListView.ItemTemplate>
<ListView.DataContext>
<ViewModel:MainViewModel/>
</ListView.DataContext>
</ListView>
</Grid>
XAML代码
using MyFareFare.Library;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace MyFareFare.ViewModel {
/// <summary>
/// This class contains properties that the main View can data bind to.
/// <para>
/// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
/// </para>
/// <para>
/// You can also use Blend to data bind with the tool's support.
/// </para>
/// <para>
/// See http://www.galasoft.ch/mvvm
/// </para>
/// </summary>
public class MainViewModel : ViewModelBase
{
/// <summary>
/// The <see cref="BonusChargesValue" /> property's name.
/// </summary>
public const string ChargesListPropertyName = "ChargeList";
public const string PageNamePropertyName = "PageName";
public const string CurrentBalancePropertyName = "CurrentBalance";
public const string ButtonTextPropertyName = "ButtonText";
private string _pageName = "My Fare";
private string _currentBalance = "";
private string _buttonText = "Show Fares";
private RelayCommand _showFaresCommand;
public ObservableCollection<BonusChargesValue> _charges = null;
public string PageName
{
get
{
return _pageName;
}
set
{
if (_pageName == value)
{
return;
}
// RaisePropertyChanging(ChargesListPropertyName);
_pageName = value;
RaisePropertyChanged(PageNamePropertyName);
}
}
public string ButtonText
{
get
{
return _buttonText;
}
set
{
if (_buttonText == value)
{
return;
}
// RaisePropertyChanging(ChargesListPropertyName);
_buttonText = value;
RaisePropertyChanged(ButtonTextPropertyName);
}
}
public string CurrentBalance
{
get
{
return _currentBalance;
}
set
{
if (_currentBalance == value)
{
return;
}
// RaisePropertyChanging(ChargesListPropertyName);
_currentBalance = value;
RaisePropertyChanged(CurrentBalancePropertyName);
}
}
/// <summary>
/// Sets and gets the Charges property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ObservableCollection<BonusChargesValue> Charges
{
get
{
return _charges;
}
set
{
if (_charges == value)
{
return;
}
// RaisePropertyChanging(ChargesListPropertyName);
_charges = value;
RaisePropertyChanged(ChargesListPropertyName);
}
}
public RelayCommand ShowFaresCommand
{
get;
set;
}
//public RelayCommand ShowFaresCommand
//{
// get
// {
// return _showFaresCommand
// ?? (_showFaresCommand = new RelayCommand(
// ()=>
// {
// _charges = new ObservableCollection<BonusChargesValue>();
// CalculateMetroFare cmcf = new CalculateMetroFare();
// if (!string.IsNullOrWhiteSpace(CurrentBalance))
// {
// _charges = cmcf.Add2ExistingCard(Convert.ToInt32(CurrentBalance));
// }
// }));
// }
//}
// public RelayCommand ShowFares { get; set; }
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
_charges = new ObservableCollection<BonusChargesValue>();
ShowFaresCommand = new RelayCommand(GetValues, () => { return true; });
// if I un-comment the below section the observable is working fine.
//Using lambda is not helping either
/* if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
// BonusChargesValue bnc = new BonusChargesValue();
_charges = new ObservableCollection<BonusChargesValue>();
_charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
_charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
}
else
{
// Code runs "for real"
_charges = new ObservableCollection<BonusChargesValue>();
// ShowFaresCommand = new RelayCommand(GetValues, () => { return true; });
ShowFaresCommand = new RelayCommand(() =>
{
CalculateMetroFare cmcf = new CalculateMetroFare();
if (!string.IsNullOrWhiteSpace(CurrentBalance))
{
var chr = cmcf.Add2ExistingCard(Convert.ToInt32(CurrentBalance));
foreach (BonusChargesValue bncv in chr)
{
Charges.Add(bncv);
}
}
});
//_charges = new ObservableCollection<BonusChargesValue>();
//_charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
//_charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
} */
}
private void GetValues()
{
CalculateMetroFare cmcf = new CalculateMetroFare();
if (!string.IsNullOrWhiteSpace(CurrentBalance))
{
var chr = cmcf.Add2ExistingCard(Convert.ToInt32(CurrentBalance));
foreach (BonusChargesValue bncv in chr)
{
Charges.Add(bncv);
}
}
}
}
查看模型
{{1}}
我不确定我做错了什么。任何帮助或指针都表示赞赏。
答案 0 :(得分:0)
我可以在这里看到几件事:
首先你的ChargesListPropertyName
是错误的,它应该是“费用”而不是“ChargeList”。
如果您正在使用MVVM Light,那么有更好的方法来调用PropertyChanged,这会阻止您再次犯这种错误(我稍后会让您检查)。
然后你的公开ObservableCollection
费用是_charges的访问者,他们也是公开的。您应该将_charges设置为private(并将其设置为null是无用的)。
最后,您的ItemsSource设置为观看费用。因此,无论您在viewmodel的构造函数之外更新_charges,List都不会知道发生了什么。我的意思是你应该总是更新费用而不是_费用。
进行这些修改并告诉我们它是否有帮助。如果没有,请更新您的代码以向我们展示您修改的内容。