如何在 XAML 中构建问卷 UserControl,其问题共享相同的答案? [英] How can I build a questionnaire UserControl in XAML whose questions share the same answers?
问题描述
我想构建一个 UserControl
来表示问卷,如下图所示(忽略样式的缺失).
I'd like to build a UserControl
to represent a questionnaire, something like that pictured below (ignore the lack of styling).
我希望能够在XAML中指定重要的内容,比如
I want to be able to specify the important content in XAML, such as
<local:QuestionnaireControl>
<local:QuestionnaireControl.Questions>
<local:QuestionAndAnswers Number="1" Question="Is this working?" />
<local:QuestionAndAnswers Number="2" Question="Are these questions sharing answers?" />
</local:QuestionnaireControl.Questions>
<local:QuestionnaireControl.Answers>
<local:Answer Value="0" Text="Yes" />
<local:Answer Value="1" Text="No" />
<local:Answer Value="2" Text="Help Me Please" />
</local:QuestionnaireControl.Answers>
</local:QuestionnaireControl>
所以我有以下 QuestionnaireControl.xaml
<UserControl x:Class="MyProject.QuestionnaireControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:local="clr-namespace:MyProject"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DataContext="{d:DesignInstance Type=local:QuestionnaireControl, IsDesignTimeCreatable=True}">
<ItemsControl ItemsSource="{Binding Questions}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='{}{0}.'}" Margin="0,0,10,0" />
<TextBlock Text="{Binding Question}" Width="220"/>
<ItemsControl ItemsSource="{Binding Answers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<RadioButton
Content="{Binding Text}"
IsChecked="{Binding IsSelected}"
GroupName="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:QuestionAndAnswers}, Path=Question}"
Margin="0,0,10,0"
/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
以及下面的QuestionnaireControl.xaml.cs
public partial class QuestionnaireControl : UserControl
{
public QuestionnaireControl()
{
InitializeComponent();
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
Questions = new List<QuestionAndAnswers> {
new QuestionAndAnswers() { Number=1, Question="Do you like pizza?" },
new QuestionAndAnswers() { Number=2, Question="Can you surf?" },
new QuestionAndAnswers() { Number=3, Question="Are you funny?" },
new QuestionAndAnswers() { Number=4, Question="Is Monday your favorite day of the week?" },
new QuestionAndAnswers() { Number=5, Question="Have you been to Paris?" },
new QuestionAndAnswers() { Number=6, Question="When sleeping, do you snore?" },
new QuestionAndAnswers() { Number=7, Question="Could you be living in a dream?" }
};
Answers = new List<Answer> {
new Answer() { Value=1, Text="Yes", IsSelected=false },
new Answer() { Value=2, Text="No", IsSelected=false },
new Answer() { Value=3, Text="Sort Of", IsSelected=false },
};
}
else
{
Questions = new List<QuestionAndAnswers>();
Answers = new List<Answer>();
}
// Copy Answers to each QuestionAndAnswers.
foreach (QuestionAndAnswers qa in Questions)
{
qa.Answers = new List<Answer>(Answers);
}
}
public List<QuestionAndAnswers> Questions
{
get { return (List<QuestionAndAnswers>)GetValue(QuestionsProperty); }
set { SetValue(QuestionsProperty, value); }
}
public static readonly DependencyProperty QuestionsProperty =
DependencyProperty.Register("Questions", typeof(List<QuestionAndAnswers>), typeof(QuestionnaireControl), new FrameworkPropertyMetadata(new List<QuestionAndAnswers>()));
public List<Answer> Answers
{
get { return (List<Answer>)GetValue(AnswersProperty); }
set { SetValue(AnswersProperty, value); }
}
public static readonly DependencyProperty AnswersProperty =
DependencyProperty.Register("Answers", typeof(List<Answer>), typeof(QuestionnaireControl), new FrameworkPropertyMetadata(new List<Answer>()));
}
public class QuestionAndAnswers
{
public int Number { get; set; }
public string Question { get; set; }
public List<Answer> Answers { get; set; }
}
public class Answer
{
public string Text { get; set; }
public int Value { get; set; }
public bool IsSelected { get; set; }
}
使用上面的代码,我可以在 Visual Studio 设计器中生成 QuestionnaireControl
上面的图像.但是,当我实际使用 QuestionnaireControl
时,根据上面的示例,会呈现问题而不是答案.有谁知道我需要调整什么?
With the code above, I'm able to produce the image above of the QuestionnaireControl
in the Visual Studio designer. But when I actually use the QuestionnaireControl
, per the example above, the questions are rendered but not the answers. Does anyone know what I need to tweak?
推荐答案
如果将控件的 Answers
属性的类型更改为 ObservableCollection
你可以处理它的 CollectionChanged
事件并复制每个问题的答案:
If you change the type of the Answers
property of the control to ObservableCollection<Answer>
you could handle its CollectionChanged
event and copy the answers to each question:
public partial class QuestionnaireControl : UserControl
{
public QuestionnaireControl()
{
InitializeComponent();
Questions = new List<QuestionAndAnswers>();
Answers = new ObservableCollection<Answer>();
Answers.CollectionChanged += Answers_CollectionChanged;
}
private void Answers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (var question in Questions)
{
question.Answers = new List<Answer>();
foreach (var answer in Answers)
{
question.Answers.Add(new Answer() { Text = answer.Text, Value = answer.Value, IsSelected = answer.IsSelected });
}
}
}
public List<QuestionAndAnswers> Questions
{
get { return (List<QuestionAndAnswers>)GetValue(QuestionsProperty); }
set { SetValue(QuestionsProperty, value); }
}
public static readonly DependencyProperty QuestionsProperty =
DependencyProperty.Register("Questions", typeof(List<QuestionAndAnswers>), typeof(QuestionnaireControl));
public ObservableCollection<Answer> Answers
{
get { return (ObservableCollection<Answer>)GetValue(AnswersProperty); }
set { SetValue(AnswersProperty, value); }
}
public static readonly DependencyProperty AnswersProperty =
DependencyProperty.Register("Answers", typeof(ObservableCollection<Answer>), typeof(QuestionnaireControl), new FrameworkPropertyMetadata(null));
}
这篇关于如何在 XAML 中构建问卷 UserControl,其问题共享相同的答案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!