0

Hi guys i want to make a radio button how get args from list. I don't understand how can i create the list to implement all args in a radio button + textbox, something like this:

Question1: What is cat?
Answer 1: Animal
Answer 2: Human
Answer 3: Stone

how can i make bind if i have something like this:

<ListBox
    HorizontalAlignment="Left"
    Height="313"
    Margin="57,29,0,0"
    VerticalAlignment="Top"
    Width="681"
    SelectionMode="Single"
    IsSynchronizedWithCurrentItem="True"
>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="This is question 1!" Margin="25" FontSize="25" />
                <RadioButton GroupName="First Question" IsChecked="False" Margin="10" Content="{Binding LoadRadioContent}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
9
  • If you're binding, the data should already be available, so you wouldn't be using a LoadRadioContent method, but the path to a property of the list item viewmodel. So as is, we don't have enough information; what does your view model look like? Commented Jun 22, 2020 at 20:40
  • @Kilazur pastebin.com/tddNp3Tm Commented Jun 22, 2020 at 20:46
  • @ClaudiuAndries try adding Set { _LoadRadioContent = value; RaisePropertyChange(); } in the setter of LoadRadioContent . To get RaisePropertyChange(), please implement the INotifyPropertyChanged's methods. Commented Jun 23, 2020 at 7:12
  • Can you please show your data class that you display in the ListBox and the initialization of the ListBox? Commented Jun 23, 2020 at 8:43
  • 1
    The data item should contain a property that holds the question, a collection of possible answers and a property that holds the correct answer. Then in your DataTemplate add another nested ItemsControl to replace the current RadioButton where ItemsControl.ItemsSource binds to the collection of possible answers. Then define a DataTemplate for the new ItemsControl.ItemTemplate. This DataTemplate contains a RadioButton where RadioButton.Content binds to the current DataContext (the possible answer). Commented Jun 23, 2020 at 8:44

1 Answer 1

1

You must create a structure of a list of questions, where each question has a list of possible answers.

The following example uses the RelayCommand implementation provided by Microsoft Docs: Relaying Command Logic. It uses a composed data model consisting of Question and Answer:

Question.cs

public class Question : INotifyPropertyChanged
{
  public Question(string summary, Answer answer)
  {
    this.Summary = summary;
    this.Answer = answer;
  }

  public string Summary { get; set; }
  public Answer Answer { get; set; }

  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

Answer.cs

public class Answer : INotifyPropertyChanged
{
  public Answer(IEnumerable<IChoice> choices)
  {
    this.Choices = choices;
  }

  // Evaluates the answer(s)
  public bool Validate()
  {
    this.IsCorrect = this.Choices.All(
      choice => choice.IsValidChoice && choice.IsSelected 
                || !choice.IsValidChoice && !choice.IsSelected);
    return this.IsCorrect;
  }

  public ICommand CheckAnswerCommand =>
    new RelayCommand(answer => Validate());
  
  public IEnumerable<IChoice> Choices { get; set; }

  private bool isCorrect;
  public bool IsCorrect
  {
    get => this.isCorrect;
    private set
    {
      this.isCorrect = value;
      OnPropertyChanged();
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

IChoice

public interface IChoice : INotifyPropertyChanged
{
  // Marks whether the choice is a valid answer
  bool IsValidChoice { get; }

  // Selects the choice as an answer
  bool IsSelected { get; set; }

  string Text { get; set; }
}

MultiChoice.cs

class MultiChoice : IChoice
{
  public MultiChoice(string text, bool isValidChoice)
  {
    this.Text = text;
    this.IsValidChoice = isValidChoice;
  }

  #region Implementation of IChoice

  public bool IsValidChoice { get; }

  private bool isSelected;    
  public bool IsSelected
  {
    get => this.isSelected;
    set
    {
      this.isSelected = value;
      OnPropertyChanged();
    }
  }

  private string text;    
  public string Text
  {
    get => this.text;
    set
    {
      this.text = value;
      OnPropertyChanged();
    }
  }

  #endregion

  #region Implementation of INotifyPropertyChanged

  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }

  #endregion
}

SingleChoice.cs

class SingleChoice : IChoice
{
  public SingleChoice(string text, bool isValidChoice)
  {
    this.Text = text;
    this.IsValidChoice = isValidChoice;
  }

  #region Implementation of IChoice

  public bool IsValidChoice { get; }    
  
  private bool isSelected;    
  public bool IsSelected
  {
    get => this.isSelected;
    set
    {
      this.isSelected = value;
      OnPropertyChanged();
    }
  }

  private string text;    
  public string Text
  {
    get => this.text;
    set
    {
      this.text = value;
      OnPropertyChanged();
    }
  }

  #endregion

  #region Implementation of INotifyPropertyChanged    

  public event PropertyChangedEventHandler PropertyChanged;    
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }

  #endregion
}

ViewModel.cs

public class ViewModel : INotifyPropertyChanged
{
  public ObservableCollection<Question> Questions { get; set; }

  public ViewModel()
  {
    this.Questions = new ObservableCollection<Question>
    {
      new Question(
        "Which number follows '1'?",
        new Answer(
          new[]
          {
            new SingleChoice("3", false), 
            new SingleChoice("15", false), 
            new SingleChoice("2", true),
            new SingleChoice("7", false)
          })),
      new Question(
        "Which creature can fly?",
        new Answer(
          new[]
          {
            new MultiChoice("Bird", true),
            new MultiChoice("Elephant", false),
            new MultiChoice("Bee", true),
            new MultiChoice("Cat", false)
          }))
    };
  }

  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

MainWindow.xaml

<Window xmlns:system="clr-namespace:System;assembly=mscorlib">
  <Window.DataContext>
    <ViewModel />
  </Window.DataContext>

  <StackPanel>
    <CheckBox Content="Answer 1 is Correct?" IsChecked="{Binding Questions[0].Answer.IsCorrect, Mode=OneWay}" />
    <CheckBox Content="Answer 2 is Correct?" IsChecked="{Binding Questions[1].Answer.IsCorrect, Mode=OneWay}" />
    <ListBox ItemsSource="{Binding Questions}">
      <ListBox.ItemTemplate>
        <DataTemplate DataType="{x:Type viewModels:Question}">
          <StackPanel>
            <TextBlock Text="{Binding Summary}" />
            <ListBox ItemsSource="{Binding Answer.Choices}">
              <ListBox.Resources>
                <DataTemplate DataType="{x:Type viewModels:SingleChoice}">
                  <RadioButton Content="{Binding Text}" 
                               GroupName="Answer"
                               IsChecked="{Binding IsSelected}"
                               Command="{Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext.Answer.CheckAnswerCommand}" />
                </DataTemplate>
                <DataTemplate DataType="{x:Type viewModels:MultiChoice}">
                  <CheckBox Content="{Binding Text}" 
                            IsChecked="{Binding IsSelected}"
                            Command="{Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext.Answer.CheckAnswerCommand}" />
                </DataTemplate>
              </ListBox.Resources>
            </ListBox>
          </StackPanel>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
  </StackPanel>
</Window>
Sign up to request clarification or add additional context in comments.

4 Comments

Ok it's a good ideea, but i don;t really understand all your code. I want to keep my code simple. What i want to make: a simple quiz (next/prev) with differite answer. You show me a method, it's great, but i want to make simple. I use Prism framework, and my code is this: css: pastebin.com/UCtBgFPV xaml: pastebin.com/veLbp7Gr, if you see, i want to have question with multiple answer(checkbox), and question with simple answer(radio button). if i have simple question i make visible first listbox, if not i make visible second listbox. I need a method to put multiple answer.
I create a IEnumerable of LoadRadioContentT but don't work, if i make simple string work. but i want to add more radioButton for one question and to keep right answer in my container. Give me a method...
Did you mean "Give me a method, please"? This "please" makes a subtle little difference, I think. What is next prev doing? I thought you show a bunch of questions in a ListBox. The code I have posted is very simple. I have updated it to support single answers and multi answers. This will work with Prism too. You may want to replace RelayCommand with Prism's DelegateCommand. What don't you understand? Please take your time to copy the short example an run it. It's a working example which will help you to understand the details. You can copy all classes to a single file for testing.
Ok thangk you very much

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.