2013-10-19 29 views
1

我正在使用MVVM模式開發我的第一個WP7.1應用程序。 (這是我在stackoverflow的第一個問題!)DataContext列表框中的ListPicker的DataContext問題

在其中一個屏幕上,我收集付款信息,如付款說明(文本框),支付模式/類型(Toolkit: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> 

我的模型(實現INotifyPropertyChanged)有一個PaymentInfo類映射到此屏幕。我的ViewModel有一個ObservableCollection<PaymentInfo> NewPaymentsInfo屬性。

將Screen的DataContext設置爲VM,並將ListBox Binding設置爲NewPaymentsInfo集合,SelectedItem設置爲另一個PaymentInfo對象NewPayInfo

ListPicker從模型中的另一個類PayType中獲取其數據(支付模式,如現金,卡等),該數據填充到VM構造函數中。

我的問題是ListPicker在屏幕上保持爲空。如果我使用<ListPickerItem>來填充ListPicker,那麼它就起作用(這是一種解決方法,因爲支付模式是預定義的;但是,我想在運行時獲取ItemSource的數據)。

我搜索了很多,但無法獲得ListPicker右側的綁定。我嘗試了RelativeSource,但沒有運氣。您的專家幫助非常需要。請讓我知道是否需要更多信息。

謝謝!


UPDATE:

這裏的型號:

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

這裏的視圖模型:(不包括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注意我使用透視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

歡迎來到SO!偉大的第一個問題你在你的ViewModel的構造函數中實例化NewPaymentsInfo嗎?如果沒有,你需要在實例化之後觸發它上面的屬性更改通知。如果您需要進一步瞭解它,您可以發佈Model/ViewModel的代碼:) – ChrisO

+0

@ChrisO - 謝謝!是的,我正在VM構造函數中實例化'NewPaymentsInfo'。我將很快發佈Model/VM代碼,並進一步嘗試解釋更多。 – NP3

回答

0

是的,所以你是正確的假設你需要一個RelativeSource綁定到你的PayTypesList集合。 RelativeSource允許您沿着可視​​樹遍歷並綁定到任何父元素。在這種情況下,我建議您前往ListBox,然後使用其DataContext訪問PaymentViewModel

幫你一個忙,下載Snoop這將允許你在運行時查看應用程序的可視化樹,並幫助選擇合適的綁定目標元素。

的的ItemsSource您ListPicker結合變成這樣:

ItemsSource="{Binding Path=DataContext.PayTypesList, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" 

這說的是結合保持向上遍歷可視化樹,直到找到ListBox類型的第一UIElement,然後以此爲目標綁定。您當然需要使用SelectedPayTypesList屬性爲您的SelectedItem設置類似的綁定。

編輯:順便說一句,我想你會想要SelectedPayType成爲PaymentInfo模型的成員,而不是PaymentViewModel。我假設你想要ListBox中的每個項目都有自己的選擇!

+0

嗯,我試過這個,但我得到AncestorType不支持的錯誤。看起來在Silverlight和WP中它不被支持!看看[這裏](http://stackoverflow.com/questions/15233072/windowsphone-relativesource-mode-findancestor-ancestortype-cannotresolve-sy) – NP3

+0

啊,在這種情況下,這一個可能會幫助http:// stackoverflow .com/questions/2291310/silverlight-4-relativesource-findancestor-binding/8564277#8564277它似乎有幾個解決方法。對不起,我不能有太大的幫助,我使用WPF而不是Silverlight。 – ChrisO

+0

感謝ChrisO提供寶貴的建議。我會看看你的鏈接,並在明天發佈更新。 – NP3