C# UWP程序化实现用户自定义检查表的入门困惑求助
一步步实现UWP自定义检查表功能
刚接触XAML确实容易有点无从下手,别担心,咱们从数据模型到UI再到逻辑一步步来搞定这个检查表功能~
第一步:定义层级任务的数据模型
首先咱们需要一个能表示「任务+子任务」的类,还要让它支持UI自动更新,所以得实现INotifyPropertyChanged接口:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; namespace Table1 { public class CheckItem : INotifyPropertyChanged { private string _title; private bool _isChecked; private ObservableCollection<CheckItem> _children; // 任务标题 public string Title { get => _title; set { _title = value; OnPropertyChanged(); } } // 是否勾选 public bool IsChecked { get => _isChecked; set { _isChecked = value; OnPropertyChanged(); // 可选功能:勾选父任务时自动勾选所有子任务,反之同理 foreach (var child in Children) { child.IsChecked = value; } } } // 子任务集合,用ObservableCollection能自动通知UI更新 public ObservableCollection<CheckItem> Children { get => _children ??= new ObservableCollection<CheckItem>(); set { _children = value; OnPropertyChanged(); } } // 属性变更通知事件 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
第二步:设计UI界面
因为是层级结构,用TreeView比ListBox更适合展示(当然如果坚持用ListBox也可以,我会在注释里标注替换方式)。咱们把输入区和显示区分开:
<Page x:Class="Table1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Table1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Padding="20"> <Grid.RowDefinitions> <!-- 输入区域行:自动高度 --> <RowDefinition Height="Auto"/> <!-- 检查表显示行:占满剩余空间 --> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- 输入任务的区域 --> <StackPanel Grid.Row="0" Orientation="Horizontal" Spacing="10" Margin="0 0 0 15"> <TextBox x:Name="InputTextBox" PlaceholderText="输入任务/子任务标题" Width="350"/> <Button x:Name="AddBtn" Content="添加" Click="AddBtn_Click"/> </StackPanel> <!-- 层级检查表显示区(TreeView版本) --> <TreeView x:Name="CheckTreeView" Grid.Row="1"> <TreeView.ItemTemplate> <!-- 用HierarchicalDataTemplate绑定层级数据 --> <HierarchicalDataTemplate x:DataType="local:CheckItem" ItemsSource="{Binding Children}"> <StackPanel Orientation="Horizontal" Spacing="8"> <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" VerticalAlignment="Center"/> <TextBlock Text="{Binding Title}" FontSize="14" VerticalAlignment="Center"/> </StackPanel> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> <!-- 如果坚持用ListBox,替换上面的TreeView为这段: <ListBox x:Name="CheckListBox" Grid.Row="1"> <ListBox.ItemTemplate> <HierarchicalDataTemplate x:DataType="local:CheckItem" ItemsSource="{Binding Children}"> <StackPanel Orientation="Horizontal" Spacing="8"> <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" VerticalAlignment="Center"/> <TextBlock Text="{Binding Title}" FontSize="14" VerticalAlignment="Center"/> </StackPanel> </HierarchicalDataTemplate> </ListBox.ItemTemplate> </ListBox> --> </Grid> </Page>
第三步:实现添加逻辑
在后台代码里处理按钮点击事件,判断当前选中的任务,把输入的内容添加到对应位置:
using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using System.Collections.ObjectModel; namespace Table1 { public sealed partial class MainPage : Page { // 存储所有根任务的集合 private ObservableCollection<CheckItem> _checkList; public MainPage() { this.InitializeComponent(); // 初始化数据源 _checkList = new ObservableCollection<CheckItem>(); CheckTreeView.ItemsSource = _checkList; // 如果用ListBox,替换成:CheckListBox.ItemsSource = _checkList; } private void AddBtn_Click(object sender, RoutedEventArgs e) { var inputContent = InputTextBox.Text.Trim(); // 空内容不处理 if (string.IsNullOrEmpty(inputContent)) return; // 创建新的任务项 var newCheckItem = new CheckItem { Title = inputContent }; // 获取当前选中的任务(TreeView版本) var selectedItem = CheckTreeView.SelectedItem as CheckItem; // 如果用ListBox,替换成:var selectedItem = CheckListBox.SelectedItem as CheckItem; if (selectedItem != null) { // 有选中项,添加为它的子任务 selectedItem.Children.Add(newCheckItem); } else { // 没有选中项,添加为根任务 _checkList.Add(newCheckItem); } // 清空输入框 InputTextBox.Text = string.Empty; } } }
额外小提示
- 如果要支持删除任务,可以加个删除按钮,获取选中项后,判断它是否是根任务(从
_checkList移除)还是子任务(从父项的Children移除)。 - 如果要支持编辑标题,可以把
TextBlock换成TextBox,绑定Title属性,设置IsReadOnly默认true,双击后改为false编辑。
内容的提问来源于stack exchange,提问作者Morilynx
相关产品推荐
相关产品推荐

