0

我正在尝试为我的大学的学位计划创建一个课程列表,当检查已上过的课程时,另一个课程会突出显示,以让用户知道该课程已满足所有先决条件。所以如果我检查微积分 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");

    }
  }
}
4

3 回答 3

1

我知道你要求简单,但在某些时候你可以回到这个,因为它是一种非常结构化和可扩展的方式来保存和使用 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>
于 2012-06-15T08:36:34.137 回答
1

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

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

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

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

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

于 2012-06-15T05:22:07.563 回答
0

为了您的方便,请尝试使用“CheckedChanged”事件。只需双击设计器上的 CheckBox。处理程序将自动添加(例如,

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {

    }

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

于 2012-06-15T05:37:41.803 回答