0
votes

Please do not worry about the length of the question, it's a very simple case but I spent two days till now and I don't know why binding is not working. I have a window to do a quiz, so I created QuestionsListBox that hold the list of questions, QuestionTextBlock to display the selected question text and AnswersListBox to display the options for answers. if a question has a pre-selected answer, AnswersListBox must accordingly load the answers and select the selected answer.

in the window code behind I created a dependency property to load the exam questions:

public static DependencyProperty QuestionsProperty = DependencyProperty.Register("Questions", typeof(List<Models.Questions>), typeof(Question));
public List<Models.Question> Questions
{
    get { return (List<Models.Question>)GetValue(QuestionsProperty); }
    set { SetValue(QuestionsProperty, value); }
}

Models are:

public class Question
{
    public short QuestionNo { get; set; }
    public byte[] QuestionImage { get; set; }
    public string QuestionText { get; set; }
    public Answer SelectedAnswer { get; set; }
    public List<Answer> Answers { get; set; }
}
public class Answer
{
    public short AnswerID { get; set; }
    public short AnswerPower { get; set; }
    public string AnswerText { get; set; }
}

in the xaml, I have the configuration as below:

<ListView x:Name="QuestionList"
      ItemsSource="{Binding ElementName=Questionctl, Path=Questions}">
    <ListView.ItemTemplate>
        <DataTemplate DataType="{x:Type model:Question}">
            <Grid>
                <TextBlock Text="{Binding Question.QuestionNo}" />
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

<TextBlock x:Name="lblText"
            Text="{Binding ElementName=QuestionList, Path=SelectedItem.QuestionText}">
</TextBlock>

<ListBox x:Name="AnswersListBox"
         ItemsSource="{Binding ElementName=QuestionList, Path=SelectedItem.Answers}"
         SelectedItem="{Binding ElementName=QuestionList, Path=SelectedItem.SelectedAnswer, Mode=TwoWay}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type model:Answer}">
            <Grid>
                <TextBlock Text="{Binding AnswerText}">
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

when I load the questions, and select any question, everything load properly. the text of the question, the list of answers, except if question has a pre-selected answer, that answer is not selected in the answer list. but if I select an answer, the model is immediately updated. if the list of answers is updating based on the binding, so why not for selected Answers?

Did I do anything wrong that prevent the selection of the answer?

1
Since it's preselected I assume you're doing something like meAnswer = answers[X];. If you're doing something like that, remember to NotifyPropertyChanged - Mateusz
You should generally implement INotifyPropertyChanged and fire the PropertyChanged event for any property that may ever change. - Clemens

1 Answers

0
votes

I figured out the reason, so in case someone faces the same issue, he can save time in debugging and trying...

the short answer is: Problem is in filling the data source and not in binding.

I'm filling the Exam data source using a web service in JSON format, and in that case, even the selected answer is having the same values as one of the answers list, when it reach the client, selected answer will NOT be considered as one of the answers. instead, it will be considered as new Answer class having the same data.

in order to rectify the issue, I did not touch my xaml because it has nothing wrong. Instead, I loop through the list after it has been filled from webservice to re-set the selected answer as one of the available answers:

private List<Models.Question> RectifyQuestions(List<Models.Question> exam)
{
    foreach(var item in exam)
    {
        if (item.SelectedAnswer != null)
        {
            item.SelectedAnswer = item.Answers.FirstOrDefault(a => a.AnswerID == item.SelectedAnswer.AnswerID);
        }
    }
    return exam;
}