You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF拖拽选时控件咨询:工时记录应用时间块拖拽实现

嘿,作为有C#和MVC背景转WPF的开发者,我完全懂你想要快速搞定这个工时记录界面的心情!针对你的场景,我整理了两种靠谱的解决方案:

现成可用的控件选项

如果你想省事儿,直接用成熟的第三方控件是最快的:

  • Telerik RadScheduleView:这款商业控件完美支持自定义15分钟时间刻度,自带拖拽选择时间块的功能,还能轻松绑定数据源。你只需要把字节数组转成对应的时间区间模型,绑定到它的Appointments集合就行。唯一的小缺点是需要授权,但能帮你省掉大量自定义逻辑的工作量。
  • DevExpress SchedulerControl:同样是商业控件,它的时间线视图可以直接配置15分钟刻度,拖拽选择、编辑时间块的逻辑都很成熟。数据绑定也很灵活,适配你把字节数组转模型的需求完全没问题。
  • WPF Toolkit 扩展组件:如果想找免费的,这个开源工具包的Calendar相关组件可以作为基础,但原生功能不够完善,需要自己扩展刻度和拖拽逻辑,适合愿意花点时间折腾的情况。
自定义实现方案(不想用第三方控件的话)

其实自己动手实现也没那么难,毕竟你有C#基础,WPF的布局和事件处理和MVC前端逻辑有不少相通之处:

1. 先搭好网格布局

用ItemsControl结合UniformGrid来构建96个时间块(24小时×4个15分钟段):

  • 计算好每个块的尺寸,比如把窗口高度均分96份,宽度可以固定或者自适应。
  • 给每个时间块绑定对应的时间区间(比如00:00-00:15),同时绑定字节数组里的状态(0=未记录,1=已记录)来控制背景色。

2. 实现拖拽选择逻辑

这部分核心是处理鼠标事件:

  • 监听MouseDown:记录起始的时间块索引,标记进入选择状态。
  • 监听MouseMove:鼠标移动时计算当前所在的时间块索引,更新选中的区间,同时实时修改字节数组对应的位置(比如把选中索引对应的位设为1)。
  • 监听MouseUp:结束选择状态,触发数据保存的逻辑。

3. 优化数据绑定

把字节数组封装成一个ViewModel,比如DailyTimeRecordViewModel,里面暴露一个TimeBlocks集合,每个TimeBlock包含StartTime、EndTime、IsSelected属性。然后把字节数组的每一位映射到IsSelected,这样UI和数据就能双向绑定,不用手动操作UI元素。

举个简单的映射逻辑示例:

public ObservableCollection<TimeBlock> TimeBlocks { get; set; } = new ObservableCollection<TimeBlock>();

public void LoadFromByteArray(byte[] dailyData)
{
    TimeBlocks.Clear();
    for (int i = 0; i < 96; i++)
    {
        var startTime = TimeSpan.FromMinutes(i * 15);
        var endTime = startTime.Add(TimeSpan.FromMinutes(15));
        // 字节数组每一位对应一个15分钟块
        var isSelected = (dailyData[i / 8] & (1 << (i % 8))) != 0;
        TimeBlocks.Add(new TimeBlock 
        { 
            StartTime = startTime, 
            EndTime = endTime, 
            IsSelected = isSelected 
        });
    }
}

4. 美化界面样式

用WPF的Style和Trigger来设置选中状态、鼠标悬停的效果,让界面更友好:

<Style TargetType="Border" x:Key="TimeBlockStyle">
    <Setter Property="Background" Value="#F5F5F5"/>
    <Setter Property="BorderBrush" Value="#E0E0E0"/>
    <Setter Property="BorderThickness" Value="0.5"/>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="#E8E8E8"/>
        </Trigger>
        <DataTrigger Binding="{Binding IsSelected}" Value="True">
            <Setter Property="Background" Value="#2196F3"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

内容的提问来源于stack exchange,提问作者Guy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:13:28