在WPF中,如何根据数据库中配置的类型添加单选按钮、复选框、组合框?

In WPF,How to add radio button , checkbox, comboBox based on the type which is configured in the database?

我完全是 WPF 的新手,我需要解决这个问题。谁能给我一个不使用代码隐藏的示例 xaml 代码。 基于questType (Check,radio, combo) 控件需要基于ObserverableCollection创建。

public class Order
{
  public int OrderCode {get;set;}
  public string Description {get;set;}
  public ObserverableCollection<question> Questions{get;set;}
}
public class question
{
   public string questType {get;set;}
   public string Question {get;set;}
   public ObserverableCollection<Answer> Answers {get;set;}
}
public class Answer
{
    public string Ans{get; set;}
}

基于任务类型(Check、radio、combo) 控件需要基于 ObserverableCollection 创建。 例子: 1001铅笔性别? o男 o女 其他 []复选框1 []复选框2 第1002章禁笔? o是 o否

以下是我的做法:

后面的代码:

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;

namespace Ans
{

    public class Order
    {
        public int OrderCode { get; set; }
        public string Description { get; set; }
        public ObservableCollection<Question> Questions { get; set; }
    }
    public class Question
    {
        public string questType { get; set; }
        public string Label { get; set; }
        public ObservableCollection<Answer> Answers { get; set; }
    }
    public class Answer
    {
        public string Ans { get; set; }
        public bool IsSelected { get; set; }
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        #region Order

        /// <summary>
        /// Order Dependency Property
        /// </summary>
        public static readonly DependencyProperty OrderProperty =
            DependencyProperty.Register("Order", typeof(Order), typeof(MainWindow),
                new FrameworkPropertyMetadata((Order)null));

        /// <summary>
        /// Gets or sets the Order property. This dependency property 
        /// indicates ....
        /// </summary>
        public Order Order
        {
            get { return (Order)GetValue(OrderProperty); }
            set { SetValue(OrderProperty, value); }
        }

        #endregion



        public MainWindow()
        {
            InitializeComponent();

            Order = new Order()
            {
                Questions = new ObservableCollection<Question>()
                {
                    new Question()
                    {
                        questType = "Combo",
                        Label = "Combo",
                        Answers = new ObservableCollection<Answer>()
                        {
                            new Answer(){Ans = "Female"},
                            new Answer(){Ans = "Male"}
                        }
                    },
                    new Question()
                    {
                        questType = "Check",
                        Label = "Multi",
                        Answers = new ObservableCollection<Answer>()
                        {
                            new Answer(){Ans = "Female"},
                            new Answer(){Ans = "Male"}
                        }
                    },
                    new Question()
                    {
                        questType = "Radio",
                        Label = "Radio",
                        Answers = new ObservableCollection<Answer>()
                        {
                            new Answer(){Ans = "Female"},
                            new Answer(){Ans = "Male"}
                        }
                    }



                }
            };

            DataContext = this;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            foreach(Question q in Order.Questions)
            {
                Console.WriteLine( q.Label + " : " + string.Join(", " , q.Answers.Where(a=>a.IsSelected).Select(a=>a.Ans)) );
            }
        }
    }
}

XAML:

<Window x:Class="Ans.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Ans"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <DataTemplate x:Key="ComboQuestion">
            <ComboBox ItemsSource="{Binding Answers}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Ans}"/>
                    </DataTemplate>
                </ComboBox.ItemTemplate>
                <ComboBox.ItemContainerStyle>
                    <Style TargetType="{x:Type ComboBoxItem}">
                        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
                    </Style>
                </ComboBox.ItemContainerStyle>
            </ComboBox>
        </DataTemplate>
        <DataTemplate x:Key="CheckQuestion">
            <ItemsControl ItemsSource="{Binding Answers}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <CheckBox Content="{Binding Ans}" IsChecked="{Binding IsSelected, Mode=TwoWay}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
        <DataTemplate x:Key="RadioQuestion">
            <ItemsControl ItemsSource="{Binding Answers}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <RadioButton Content="{Binding Ans}" IsChecked="{Binding IsSelected, Mode=TwoWay}" GroupName="{Binding DataContext.Label, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
    </Window.Resources>
    <Grid>

        <ItemsControl ItemsSource="{Binding Order.Questions}" Grid.IsSharedSizeScope="True">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <TextBlock Text="{Binding Label}"/>

                        <ContentControl x:Name="ccQuestion" Grid.Column="1" Content="{Binding}" Margin="10"/>
                    </Grid>
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding questType}" Value="Combo">
                            <Setter TargetName="ccQuestion" Property="ContentTemplate" Value="{StaticResource ComboQuestion}"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding questType}" Value="Check">
                            <Setter TargetName="ccQuestion" Property="ContentTemplate" Value="{StaticResource CheckQuestion}"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding questType}" Value="Radio">
                            <Setter TargetName="ccQuestion" Property="ContentTemplate" Value="{StaticResource RadioQuestion}"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>


        <Button Content="Order" Click="Button_Click" VerticalAlignment="Bottom"/>
    </Grid>
</Window>

我唯一添加到您的模型的是 IsSelected 属性,它可以让我知道这个答案是否是 selected。

另一件重要的事情是收音机。他们的 GroupName 属性 定义了范围。因此,如果未设置 GroupName,则在一个问题中单击收音机时,它将在另一个问题中取消 select 收音机。我在我的解决方案中使用了问题标签,但它仅在标签是唯一的情况下才有效。

另一点是,如果您有 3-5 个问题类型并且它们仅基于问题类型,则数据触发器是可以的。但是,对于更复杂的场景,您可以查找 ItemTemplateSelector。它允许编写 C# 代码 select 基于 ItemsControl 中每个项目的模板。