使用 C# 创建动态复选框列表

本文关键字:复选框 列表 动态 创建 使用 | 更新日期: 2023-09-27 18:37:11

我试图为我的大学的学位计划创建一个课程列表,当检查已参加的课程时,另一个班级会突出显示,让用户知道该课程已满足所有先决条件。 因此,如果我检查微积分 1,物理 1 将突出显示。

我是 C# 的新手,我对语言和 .NET 框架可以做什么没有深入的了解,所以我要求一个很好的简单直接答案,如果你能准确地解释代码中发生的事情,那将是非常棒的。谢谢

这是我到目前为止所拥有的。 只是一个基本的概念证明 WPF

<Window x:Class="degree_plan.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Degree Planner" Height="350" Width="525" Name="Degree">
    <Grid>
        <CheckBox Content="Math 1412" Height="16" HorizontalAlignment="Left" Margin="34,40,0,0" Name="checkBox1" VerticalAlignment="Top" />
        <CheckBox Content="Physics 1911" Height="16" HorizontalAlignment="Left" Margin="34,62,0,0" Name="checkBox2" VerticalAlignment="Top" />
    </Grid>
</Window>

这是 C# 代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation; 
using System.Windows.Shapes;
namespace degree_plan
   {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
   public partial class MainWindow : Window
   {
      public MainWindow()
      {
        InitializeComponent();
       // if (checkBox1.Checked)
         //   Console.WriteLine("physics 1");
    }
  }
}

使用 C# 创建动态复选框列表

您可以为复选框注册事件处理程序:

AddHandler(CheckBox.CheckedEvent, new RoutedEventHandler(CheckBox_Click));

然后,创建事件处理程序:

private void CheckBox_Click(object sender, RoutedEventArgs e)
{
    CheckBox checkbox = e.Source as CheckBox
    //...
}

事件处理程序中的checkbox变量是单击以引发事件的复选框。您可以选中它所在的复选框,然后启用依赖于它的所有选项。

我知道

你要求简单,但在某些时候你可以回到这个,因为它是一种非常结构化和可扩展的方式来保存和使用WPF中的数据

我会考虑在自己的结构中量化类,每个类都有一个必须事先完成的先决条件类的列表,我想建议使用以下来实现你所追求的(对不起,有点长!

您将获得由复选框表示的类列表,只有在所有先决条件类完成后才能选中一个类,它们具有名称和描述,并且可以根据需要在UI上进行自定义。

创建新的 WPF 应用程序并添加以下类。类.cs

public class Class : Control, INotifyPropertyChanged
{
    // Property that's raised to let other clases know when a property has changed.
    public event PropertyChangedEventHandler PropertyChanged;
    // Flags to show what's going on with this class.
    bool isClassComplete;
    bool isPreComplete;
    // Some other info about the class.
    public string ClassName { get; set; }
    public string Description { get; set; }
    // A list of prerequisite classes to this one.
    List<Class> prerequisites;
    // public property access to the complete class, you can only set it to true
    // if the prerequisite classes are all complete.
    public bool IsClassComplete
    {
        get { return isClassComplete; }
        set
        {
            if (isPreComplete)
                isClassComplete = value;
            else
                if (value)
                    throw new Exception("Class can't be complete, pre isn't complete");
                else
                    isClassComplete = value;
            PropertyChangedEventHandler temp = PropertyChanged;
            if (temp != null)
                temp(this, new PropertyChangedEventArgs("IsClassComplete"));
        }
    }
    // public readonly property access to the complete flag.
    public bool IsPreComplete { get { return isPreComplete; } }
    public Class()
    {
        prerequisites = new List<Class>();
        isPreComplete = true;
    }
    // adds a class to the prerequisites list.
    public void AddPre(Class preClass)
    {
        prerequisites.Add(preClass);
        preClass.PropertyChanged += new PropertyChangedEventHandler(preClass_PropertyChanged);
        ValidatePre();
    }
    // removes a class from the prerequisites lists.
    public void RemovePre(Class preClass)
    {
        prerequisites.Remove(preClass);
        preClass.PropertyChanged -= new PropertyChangedEventHandler(preClass_PropertyChanged);
        ValidatePre();
    }
    // each time a property changes on one of the prerequisite classes this is run.
    void preClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "IsClassComplete":
                // check to see if all prerequisite classes are complete/
                ValidatePre();
                break;
        }
    }
    void ValidatePre()
    {
        if (prerequisites.Count > 0)
        {
            bool prerequisitesComplete = true;
            for (int i = 0; i < prerequisites.Count; i++)
                prerequisitesComplete &= prerequisites[i].isClassComplete;
            isPreComplete = prerequisitesComplete;
            if (!isPreComplete)
                IsClassComplete = false;
        }
        else
            isPreComplete = true;
        PropertyChangedEventHandler temp = PropertyChanged;
        if (temp != null)
            temp(this, new PropertyChangedEventArgs("IsPreComplete"));
    }
}

现在在 MainWindow 的代码后面.cs您可以创建一个类集合,我已经在构造函数中完成了这一点,并提供了一个可观察的类集合,因此当添加新类时,您无需执行任何操作即可让它们显示在 UI 上

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public ObservableCollection<Class> Classes
    {
        get { return (ObservableCollection<Class>)GetValue(ClassesProperty); }
        set { SetValue(ClassesProperty, value); }
    }
    public static readonly DependencyProperty ClassesProperty = DependencyProperty.Register("Classes", typeof(ObservableCollection<Class>), typeof(MainWindow), new UIPropertyMetadata(null));
    public MainWindow()
    {
        InitializeComponent();
        Class math = new Class()
        {
            ClassName = "Math 1412",
            Description = ""
        };
        Class physics = new Class()
        {
            ClassName = "Physics 1911",
            Description = "Everything everywhere anywhen",
        };
        physics.AddPre(math);
        Classes = new ObservableCollection<Class>();
        Classes.Add(math);
        Classes.Add(physics);
    }
}

最后一步是告诉 WPF 一个类在用户界面上应该是什么样子,这是在资源中完成的,为了简化示例,我把它放在 MainWindow.xaml 文件中。

<Window x:Class="WpfApplication8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication8"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <!-- This tells WPF what a class looks like -->
        <Style TargetType="{x:Type local:Class}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:Class}">
                        <StackPanel Orientation="Horizontal" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                            <!-- Checkbox and a text label. -->
                            <CheckBox  IsEnabled="{Binding IsPreComplete}" IsChecked="{Binding IsClassComplete}" />
                            <TextBlock Margin="5,0,0,0" Text="{Binding ClassName}" ToolTip="{Binding Description}"/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid>
        <!-- This draws the list of classes from the property in MainWindow.cs-->
        <ItemsControl ItemsSource="{Binding Classes}"/>
    </Grid>
</Window>

为了您的方便,尝试使用"已检查更改"事件。只需双击设计器上的复选框。处理程序将自动添加(例如,

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
    }

.然后在那里添加你的代码。但是,这很耗时(因为您必须为每个复选框添加处理程序)。但是,在这个阶段,您将很容易理解。