ListView中的UWP ListView不遵守INotifyPropertyChanged

用户名

我正在尝试创建Windows 10应用程序以提供问题列表;每个问题都显示问题文本(TextBlock)和可能的答案列表(指向由ToggleButton组成的DataTemplate的ListView)。

程序启动,并显示每个Answer / PossibleAnswer,到目前为止一切顺利。现在我想将每个问题限制为一个答案,这意味着检查一个可能的一个可能的overbleanswer(togglebutton),必须取消选中该问题的其他问题。问题是尽管我已经在MayaAnswer类中实现了INotifyPropertyChanged并调用了适当的方法,但事实并非如此。我什至为Answer类实现了此功能,希望对它有所帮助,但没有帮助。

我在做什么显然很蠢吗​​?任何帮助将不胜感激。

注意:我使用的是ToggleButtons,因为在一个问题中选中单选按钮将取消在所有其他问题中选中单选按钮。

我的XAML文件:(一个ListView [针对每个问题]指向由TextBlock(问题文本)和ListView [PossibleAnswers]组成的DataTemplate)

<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文件:(一个页面演示一个Answers列表,每个答案都包含一个可能的答案列表)

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));
        }
    }
}
周杰伦

要解决此问题,我们可以将的Binding Mode设置IsCheckedTwoWay如下所示:

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

对于{Binding}标记扩展,在大多数情况下,默认模式是单向。而且它对只读数据也很有效。如果我们希望用户对UI中的值所做的更改被自动推回到数据源中,则需要使用双向绑定,它对于读写数据非常有效。如果我们在此处使用单向绑定,则在用户单击ToggleButton之后,绑定将失效,因此您的代码将无法工作。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章