WPF 自定义控件实现定时自动读秒

目标:使用自定义控件实现双击控件自动读秒并且跳出弹窗,控件自动读秒倒计时,弹窗显示当前时间。

1.添加一个自定义控件,在控件里面添加一个Border控件,设置相关属性,再在border中添加一个TextBlock控件,读秒时间显示在TextBlock中。

控件设计Generic.Xaml代码如下:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyControl1">

    <Style TargetType="{x:Type local:CustomControl1}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                    <Border Background="Purple"
                            BorderBrush="Black"
                            BorderThickness= "2"
                            Width="200" Height="150">
                        <TextBlock x:Name="MyTbl" Margin="50,50" Background="LightYellow"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

2.在后台代码中需要添加两个依赖属性,这里用一个string类型的Times属性用来设置读秒的时间,一个ICommand类型的Clickcmd接口用来binding ViewModel里面的command的函数。

后台逻辑CustumControl1.cs代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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 MyControl1
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:MyControl1"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:MyControl1;assembly=MyControl1"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
    /// 并重新生成以避免编译错误:
    ///
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:CustomControl1/>
    ///
    /// </summary>
    public class CustomControl1 : Control
    {
        static CustomControl1()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
        }

        //添加一个string类型的 属性 Times
        public string Times
        {
            get { return (string)GetValue(TimesProperty); }
            set { SetValue(TimesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Times.  This enables animation, styling, binding, etc...
        //注册依赖属性,PropertyMetadata是给属性元数据,也就是属性的默认值
        public static readonly DependencyProperty TimesProperty =
            DependencyProperty.Register("Times", typeof(string), typeof(CustomControl1), new PropertyMetadata("6"));


        //添加命令属性
        public ICommand Clickcmd
        {
            get { return (ICommand)GetValue(ClickcmdProperty); }
            set { SetValue(ClickcmdProperty, value); }
        }

        //注册依赖属性,PropertyMetadata是给属性元数据,也就是属性的默认值
        // Using a DependencyProperty as the backing store for Clickcmd.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ClickcmdProperty =
            DependencyProperty.Register("Clickcmd", typeof(ICommand), typeof(CustomControl1), new PropertyMetadata(null));


        //重写OnApplyTemplate方法,用户在使用该控件时系统会自动调用的方法。
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            //给事件添加方法
            MouseDoubleClick += CustomControl1_MouseDoubleClick;
        }

        //需要添加的方法
        private void CustomControl1_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //1.读秒功能的实现
            //请求需要的元素TextBlock
            var tem = GetTemplateChild("MyTbl") as TextBlock;
            string s = tem.Text;
            //将属性Times的值赋给Text
            tem.Text = Times;
            var temint = int.Parse(Times);
            Task.Run(() =>
            {
                do
                { 
                    //跨线程访问数据
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        tem.Text = (temint--).ToString();
                        Times = temint.ToString();
                    });
                    Thread.Sleep(1000);
                }
                while (temint != 0);
                Application.Current.Dispatcher.Invoke(() =>
                {
                    tem.Text = s;
                });
            });

            //2.弹出对话框的实现
            //通过ICommand接口绑定ViewModel里Command函数
            Clickcmd.Execute(this);
        }
    }
}

3.ViewModel代码如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Prism;
using Prism.Commands;
using Prism.Mvvm;

namespace MyControl1
{
    internal class ViewModel:BindableBase
    {
        public ViewModel()
        {
            ClickCmd = new DelegateCommand(Click);
        }

        public DelegateCommand ClickCmd { get; set; }

        public void Click() 
        {
            MessageBox.Show(DateTime.Now.ToString());
        }
    }

}

4.在MainWindow中使用自定义控件:

<Window x:Class="MyControl1.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:MyControl1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <local:CustomControl1 Times="6" Clickcmd="{Binding ClickCmd}"/>
    </Grid>
</Window>

注意:在MainWindow.Xmal.cs中记得设置数据源!!!

namespace MyControl1
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //数据源!!!
            this.DataContext = new ViewModel();
        }
    }
}

5.实现效果如下:

 双击后:

MainWindow 2023-08-24 10-04-45

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值