2016-09-16 51 views
0

我試圖創建一個Windows 10應用程序提供問題列表;每個問題都會顯示問題文本(TextBlock)和可能的答案列表(ListView指向由ToggleButton組成的DataTemplate)。列表視圖中的UWP ListView不尊重INotifyPropertyChanged

該程序啓動並顯示每個Answer/PossibleAnswer,到目前爲止非常好。現在我想限制每個問題到一個單一的答案,這意味着當一個PossibleAnswer(ToggleButton)被選中時,那個問題的其他人必須是Unchecked。 問題是,儘管我在PossibleAnswer類中實現了INotifyPropertyChanged並調用了適當的方法,但這並未發生。我甚至在Answer類中實現了它,希望它有所幫助,但它沒有。

我在做什麼顯然愚蠢?任何幫助將不勝感激。

注:我正在使用ToggleButtons,因爲在一個問題中檢查RadioButton將取消選中所有其他問題中的RadioButton。

我的XAML文件:(A ListView控件[對於每一個問題]指向由一個TextBlock(問題文本)和一個ListView的一個DataTemplate [PossibleAnswers])

<Page x:Class="QuestionsnAnswers.MainPage" ... > 
    <Page.Resources> 
     <DataTemplate x:Key="myAnswersTemplate" x:DataType="local:Answer"> 
      <RelativePanel> 
       <TextBlock Text="{Binding QuestionText}"/> 
       <ListView Margin="0, 20 ,0 ,0" 
          ItemsSource="{Binding PossibleAnswers}" 
          ItemTemplate="{StaticResource myPossibleAnswersTemplate}"> 
       </ListView> 
      </RelativePanel> 
     </DataTemplate> 

     <DataTemplate x:Key="myPossibleAnswersTemplate" x:DataType="local:PossibleAnswer"> 
      <ToggleButton Content="{Binding PossibleAnswerText}" IsChecked="{Binding IsChecked}" Click="PossibleAnswerClicked" /> 
     </DataTemplate> 
    </Page.Resources> 

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <ListView Name="uiQuestionsnAnswers" ItemTemplate="{StaticResource myAnswersTemplate}"/> 
    </Grid> 
</Page> 

我的MainPage文件:(一單頁證明答案的列表,每個PossibleAnswers列表)

public sealed partial class MainPage : Page 
{ 
    ObservableCollection<Answer> Answers = new ObservableCollection<Answer>(); 

    public MainPage() 
    { 
     this.InitializeComponent(); 

     //populate example answers 
     Answers.Add(new Answer { AnswerId = 1, QuestionText = "Question 1" }); 
     Answers.Add(new Answer { AnswerId = 2, QuestionText = "Question 2" }); 
     Answers.Add(new Answer { AnswerId = 3, QuestionText = "Question 3" }); 
     uiQuestionsnAnswers.ItemsSource = Answers; 
    } 

    private void PossibleAnswerClicked(object sender, RoutedEventArgs e) { 
     //get the reference to this togglebutton's PossibleAnswer and update the model. 
     ListViewItemPresenter parent = VisualTreeHelper.GetParent(sender as DependencyObject) as ListViewItemPresenter; 
     PossibleAnswer possAnswer = parent.Content as PossibleAnswer; 
     possAnswer.IsChecked = true; 
    } 
} 


class Answer : INotifyPropertyChanged { 
    public int AnswerId { get; set; } 
    public string QuestionText { get; set; } 
    public ICollection<PossibleAnswer> PossibleAnswers { get; set; } 
    public int ChosenPossibleAnswerId { get; set; } 

    public Answer() { 
     PossibleAnswers = new List<PossibleAnswer>(); 
     PossibleAnswers.Add(new PossibleAnswer { ThisAnswer = this, PossibleAnswerId = 1, PossibleAnswerText = "yes" }); 
     PossibleAnswers.Add(new PossibleAnswer { ThisAnswer = this, PossibleAnswerId = 2, PossibleAnswerText = "no" }); 
     PossibleAnswers.Add(new PossibleAnswer { ThisAnswer = this, PossibleAnswerId = 3, PossibleAnswerText = "I don't know" }); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    public void NotifyPropertyChanged(String propertyName = "") { 
     if (PropertyChanged != null) { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    internal void setChosenAnswer(int possibleAnswerId) { 
     //record this possibleAnswer as the answer to this question. 
     ChosenPossibleAnswerId = possibleAnswerId; 

     foreach (PossibleAnswer possAnswer in PossibleAnswers) { 
      if (possAnswer.PossibleAnswerId != ChosenPossibleAnswerId) { 
       possAnswer.IsChecked = false; 
       Debug.WriteLine("Answer " + AnswerId + " has unchecked possible answer " + possAnswer.PossibleAnswerId); 
      } 
     } 
     NotifyPropertyChanged(); 
    } 
} 


class PossibleAnswer : INotifyPropertyChanged { 
    public Answer ThisAnswer { get; set; } 
    public int PossibleAnswerId { get; set; } 
    public string PossibleAnswerText { get; set; } 

    private bool _IsChecked = false; 
    public bool IsChecked { 
     get { 
      return _IsChecked; 
     } 
     set { 
      _IsChecked = value; 
      if (value == true) { 
       ThisAnswer.setChosenAnswer(PossibleAnswerId); 
      } 
      else { 
       NotifyPropertyChanged("IsChecked"); 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    public void NotifyPropertyChanged(String propertyName = "") { 
     if (PropertyChanged != null) { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

回答

1

要解決這個問題,我們可以在IsCheckedBinding Mode設置爲TwoWay像以下:

<ToggleButton Click="PossibleAnswerClicked" Content="{Binding PossibleAnswerText}" IsChecked="{Binding IsChecked, Mode=TwoWay}" /> 

對於{Binding} markup extension,在大多數情況下,默認模式是單向的。它適用於只讀數據。如果我們希望用戶對用戶界面中的值所做的更改會自動推回到數據源中,那麼我們需要使用雙向綁定,並且對於讀寫數據而言,它可以很好地工作。如果我們在這裏使用單向綁定,在用戶單擊ToggleButton後綁定將失效,因此您的代碼將無法工作。

+0

完美的工作!謝謝。 – user328414