我正在使用MVVM模式开发我的第一个WP7.1应用程序。 (这是我在stackoverflow上的第一个问题!)
在其中一个屏幕中,我使用“添加信息”按钮收集付款说明(文本框),付款方式/类型(工具包:ListPicker),付款到期日期(工具包:DatePicker)等付款信息。它包含在ListBox中。
<ListBox x:Name="AddPayListBox" ItemsSource="{Binding NewPaymentsInfo}" SelectedItem="{Binding NewPayInfo}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBox x:Name="DescInput" Text="{Binding PayDesc, Mode=TwoWay}"/>
<toolkit:ListPicker x:Name="TypeInput" Header="Mode:" CacheMode="BitmapCache"
ItemsSource="{Binding DataContext.PayTypesList}"
SelectedItem="{Binding DataContext.SelectedPayTypesList, Mode=TwoWay}">
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=PayTypesList.PayTypeDesc}"/>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
</toolkit:ListPicker>
<toolkit:DatePicker x:Name="DateInput" Value="{Binding DueDate, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="btnAddPay" Content="Add" Command="{Binding AddCommand}" />
</StackPanel>
我的模型(Implements INotifyPropertyChanged)有一个映射到此屏幕的类PaymentInfo。我的ViewModel具有ObservableCollection<PaymentInfo> NewPaymentsInfo
属性。
屏幕的DataContext设置为VM,ListBox Binding设置为NewPaymentsInfo
集合,SelectedItem
集合到另一个PaymentInfo
对象NewPayInfo
。
ListPicker从Model中的另一个类PayType
获取其数据(支付模式,如Cash,Card等),该类填充在VM Constructor中。
我的问题是ListPicker在屏幕上保持为空。如果我使用<ListPickerItem>
来填充ListPicker,那么它可以正常工作。(这是一种解决方法,因为付款模式是预定义的;但是,我想在运行时获取ItemSource
的数据。)
我搜索了很多但是无法获得ListPicker的Bindings。我试过RelativeSource
,但没有运气。非常需要您的专业帮助。如果需要更多信息,请告诉我。
谢谢!
更新:
这是模型:
public class PaymentInfo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _PayDesc;
public string PayDesc
{
get { return _PayDesc; }
set
{
_PayDesc = value;
RaisePropertyChanged("PayDesc");
}
}
private byte _PayType;
public byte PayType
{
get { return _PayType; }
set
{
_PayType = value;
RaisePropertyChanged("PayType");
}
}
private DateTime _DueDate;
public DateTime DueDate
{
get { return _DueDate; }
set
{
_DueDate = value;
RaisePropertyChanged("DueDate");
}
}
}
public class SupportedPayTypes : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private byte _PayTypeIdx;
public byte PayTypeIdx
{
get { return _PayTypeIdx; }
set
{
_PayTypeIdx = value;
RaisePropertyChanged("PayTypeIdx");
}
}
private string _PayTypeDesc;
public string PayTypeDesc
{
get { return _PayTypeDesc; }
set
{
_PayTypeDesc = value;
RaisePropertyChanged("PayTypeDesc");
}
}
}
这是ViewModel :(不包括AddCommand,因为该部分工作正常)
public class PaymentViewModel
{
public ObservableCollection<PaymentInfo> NewPaymentsInfo { get; set; }
public PaymentInfo NewPayInfo;
public ICommand AddCommand { get; set; }
public ObservableCollection<SupportedPayTypes> PayTypesList;
public SupportedPayTypes SelectedPayTypesList;
public PaymentViewModel()
{
AddCommand = new DelegateCommand<PaymentSetup>(AddAction);
PayTypesList = new ObservableCollection<SupportedPayTypes>();
PayTypesList.Add(new SupportedPayTypes() { PayTypeIdx = 0, PayTypeDesc = "Cash" });
PayTypesList.Add(new SupportedPayTypes() { PayTypeIdx = 1, PayTypeDesc = "Credit Card" });
//SelectedPayTypesList = PayTypesList[0];
SelectedPayTypesList = new SupportedPayTypes();
SelectedPayTypesList.PayTypeIdx = PayTypesList[0].PayTypeIdx;
SelectedPayTypesList.PayTypeDesc = PayTypesList[0].PayTypeDesc;
NewPaymentsInfo = new ObservableCollection<PaymentInfo>();
NewPayInfo = new PaymentInfo();
NewPayInfo.PayDesc = "";
NewPayInfo.PayType = SelectedPayTypesList.PayTypeIdx;
NewPayInfo.DueDate = DateTime.Now;
NewPaymentsInfo.Add(NewPayInfo);
}
}
最后,这是MainPage.xaml.cs
N.B.我正在使用Pivot MainPivot
,相关屏幕为AddView
public partial class MainPage : PhoneApplicationPage
{
private PaymentViewModel vm;
public MainPage()
{
InitializeComponent();
vm = new PaymentViewModel();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
AddView.DataContext = vm;
MainPivot.SelectedIndex = 1;
}
}
如果发现任何遗失,请告诉我?我已经到了我的智慧结束:)
谢谢!
答案 0 :(得分:0)
是的,所以你认为你需要一个RelativeSource
绑定来到你的PayTypesList
集合是正确的。 RelativeSource
允许您沿着可视树向上走,并绑定到任何父元素。在这种情况下,我建议您走到ListBox
,然后使用其DataContext
访问PaymentViewModel
。
请帮忙并下载Snoop,这样您就可以在运行时查看应用程序的可视树,并帮助为绑定选择合适的目标元素。
ListPicker上的ItemsSource绑定变为:
ItemsSource="{Binding Path=DataContext.PayTypesList, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
这告诉绑定继续遍历可视树,直到它找到类型UIElement
的第一个ListBox
,然后将其用作绑定的目标。您当然希望使用SelectedItem
属性为SelectedPayTypesList
添加类似的绑定。
编辑:顺便说一下,我认为您希望SelectedPayType
成为PaymentInfo
模型的成员,而不是PaymentViewModel
。我假设您希望ListBox中的每个项目都有自己的选择!