WPF C# MVVM 单选按钮加载列表内容



嗨,伙计们,我想制作一个单选按钮如何从列表中获取参数。我不明白如何创建列表以在单选按钮+文本框中实现所有参数,如下所示:

问题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实现。 它使用由QuestionAnswer组成的组合数据模型:

问题.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>

最新更新