嗨,伙计们,我想制作一个单选按钮如何从列表中获取参数。我不明白如何创建列表以在单选按钮+文本框中实现所有参数,如下所示:
问题1:什么是猫?
答案1:动物
答案2:人类
答案3:石头
如果我有这样的东西,我该如何进行绑定:
<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>
您必须创建问题列表的结构,其中每个问题都有一个可能的答案列表。
以下示例使用 Microsoft Docs:中继命令逻辑提供的RelayCommand
实现。 它使用由Question
和Answer
组成的组合数据模型:
问题.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));
}
}
答.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));
}
}
呵呵
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; }
}
多选.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
}
单选.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
}
视图模型.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>