WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示

news/2024/10/11 17:23:51

1、新建了一个用户控件,里面画了一个实心圆,以及一个文本控件的组合,当作我要实验使用的用户控件(TestUserControl)。

 

2、在主窗体里面进行引用,可以看到引用以后,会在工具箱上显示新增的用户控件

3、为了测试方便,我直接在先前的Lo'gin页面直接进行添加该用户控件,效果如下。

 

4、运行效果如下。由于该用户控件没有设置过任何属性,所以现在是没有任何事件、也没有办法更改默认文本等信息的。

 

5、接下来进行设置属性,用于可以直接更改TextName属性的Text值。设置一个MyText属性,用于可以获取和设置用户控件内的TextBlock的Text值。

 

6、然后可以在Xaml里面直接通过更改MyText的属性,来更新显示的Text值。如下图所示,设置MyText属性后,设置值为666,同步更新成666了。

 

7、但是如果想要实现双向绑定,其实还不太够,直接Binding会提示错误XDG0062:Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.String'. 如图。

 

8、以上问题可以通过自定义依赖属性来解决。在用户控件的设计器交互代码类(TestUserControl)里面,新增以下代码,功能如图所示。

 

9、现在在xaml里面,设置Binding就不会提示错误了。

 

10、并且也可以直接设置值,效果同上面设置属性以后直接写值效果一样。

 

11、在Login页面的ViewModel里面,新增属性提供给双向绑定使用。

 

12、设置MyText进行Binding到刚刚写的ViewModel的属性TestText上。

 

13、运行效果如下图所示,说明双向绑定成功了。

 

14、接下来对用户控件设置单击事件的双向绑定。先设置Command有关的依赖属性。

 

15、一些有关方法和其他的属性设置,就不做过多介绍了,看图说话。

 

16、然后是关键的一步,需要设置单机事件与Command属性关联。当然,Command是命名得来的,所以也可以使用其他的命名,也都是OK的,不用在意这些细节,只是默认情况下,单击都喜欢用Command。如果自带的控件也没有双击、右键等双向绑定,也可以通过设置依赖属性来实现。

 

17、在ViewModel里面定义单击事件以及有关执行的方法。方法为一个弹出消息框。

 

18、使用Command进行绑定事件名称。

 

19、运行,并单击实心圆的效果,并弹出提示框,说明单击事件通过依赖属性进行设置成功。

 

20、接下来测试一下带参数的事件。在viewmodel里面,对刚才无参数的事件,改为带一个string参数的。

 

21、在xaml里面,传入一个字符串参数,就叫 Hello world

 

22、运行,并点击实心圆后效果如图所示,说明带参数也是OK的。

 

23、其他套路如出一辙,大佬们可以自行尝试,例如通过设置背景依赖属性,变更实心圆的背景,而不是整个用户控件(正方形)的背景。这部分本来也要写一个给大佬们压压惊,由于时间关系,大佬们可以自己尝试玩一下。

提示:背景 Background是系统自带的,所以需要new。通过属性依赖进行更改圆的颜色,而不是背景色。有兴趣的大佬或者需要学习的,可以动手玩一玩,加深印象。

 

以上就是该文章的全部内容,如果对你有帮助,欢迎大佬点赞、留言与转发。如需转发,请注明我的博客出处:

https://www.cnblogs.com/weskynet/p/16290422.html

 

以下是有关最终的源代码:

TestUserControl:

复制代码
<Grid><Viewbox Stretch="Fill"><Canvas Width="200" Height="200"><Ellipse Name="rect3" Width="200" Height="200" Stroke="Orange" StrokeThickness="100" ></Ellipse></Canvas></Viewbox><TextBlock x:Name="TextName" Text="123" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock></Grid>
复制代码
复制代码
 public partial class TestUserControl : UserControl{public TestUserControl(){InitializeComponent();}
    public static readonly DependencyProperty MyTextProperty =DependencyProperty.Register("MyText", typeof(String), typeof(TestUserControl),new PropertyMetadata((String)null, new PropertyChangedCallback(TextChanged)));private static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){TestUserControl control = d as TestUserControl;if (control != null){String oldText = e.OldValue as String;  // 旧的值String newText = e.NewValue as String; // 更新的新的值control.UpdateMyText(newText);}}private void UpdateMyText(string newValue){this.TextName.Text = newValue;}[Bindable(true)][Category("Appearance")] // using System.ComponentModel;public string MyText{get{return (String)GetValue(MyTextProperty);}set{SetValue(MyTextProperty, value);}}public static readonly DependencyProperty CommandProperty =DependencyProperty.Register("Command", typeof(ICommand), typeof(TestUserControl),new PropertyMetadata((ICommand)null, new PropertyChangedCallback(CommandChanged)));public static readonly DependencyProperty CommandParameterProperty =DependencyProperty.Register("CommandParameter", typeof(object), typeof(TestUserControl));public static readonly DependencyProperty CommandTargetProperty =DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(TestUserControl));private static void CommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){TestUserControl control = d as TestUserControl;if (control != null){ICommand oldCommand = e.OldValue as ICommand;ICommand newCommand = e.NewValue as ICommand;control.UpdateCommand(oldCommand, newCommand);}}private void UpdateCommand(ICommand oldCommand, ICommand newCommand){if (oldCommand != null){oldCommand.CanExecuteChanged -= CanExecuteChanged;}if (newCommand != null){newCommand.CanExecuteChanged += CanExecuteChanged;}}private void CanExecuteChanged(object sender, EventArgs e){RoutedCommand command = this.Command as RoutedCommand;if (command != null){this.IsEnabled = command.CanExecute(CommandParameter, CommandTarget);}else if (this.Command != null){this.IsEnabled = this.Command.CanExecute(CommandParameter);}}public ICommand Command{get { return (ICommand)GetValue(CommandProperty); }set { SetValue(CommandProperty, value); }}public object CommandParameter{get { return GetValue(CommandParameterProperty); }set { SetValue(CommandParameterProperty, value); }}public IInputElement CommandTarget{get { return (IInputElement)GetValue(CommandTargetProperty); }set { SetValue(CommandTargetProperty, value); }}protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e){base.OnMouseLeftButtonDown(e);RoutedCommand command = Command as RoutedCommand;if (command != null)command.Execute(CommandParameter, CommandTarget);else if (Command != null)this.Command.Execute(CommandParameter);}}

}

复制代码

LoginViewModel:

复制代码
public class LoginViewModel: BindableBase{public LoginViewModel(){
    }public string _testText = "999";public string TextText{get { return _testText; }set { SetProperty(ref _testText, value); }}private DelegateCommand&lt;string&gt; _testCommand;public DelegateCommand&lt;string&gt; TestCommand{get{if (_testCommand == null){_testCommand = new DelegateCommand&lt;string&gt;(ExecuteTestCommand);}return _testCommand;}}private void ExecuteTestCommand(string value){MessageBox.Show(value);}}</pre>
复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/70290.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

华为交换机配置-端口隔离

端口隔离(port-isolate) 1.端口隔离 配置端口隔离功能,可实现本台交换机的两个接口之间的二层数据的隔离,而三层数据互通 拓扑图<sw1>sys //配置全局端口隔离模式为二层隔离(l2)、三层隔离(l3) [sw1]port-isolate mode l2 [sw1]interface GigabitEthernet 0/0/1 …

Sublime

Sublime激活快捷键 Alt + F3 查找内容 全部选择,可以统一替换或 手动修改

20222418 2024-2025-1 《网络与系统攻防技术》实验一实验报告

1.实验内容 本周课程内容为缓冲区溢出和shellcode:2.实验过程 (1)直接修改程序机器指令,改变程序执行流程 ①首先根据网上教程安装好kali虚拟机,更改主机名为heshan;下载目标文件pwn1,将pwn1文件放入共享文件夹并在VMware中设置共享以便使用,并将其重命名为pwn20222418…

mysqldump文件中有SET @@SESSION.SQL_LOG_BIN= 0;解决方法

mysqldump文件中有SET @@SESSION.SQL_LOG_BIN= 0mysqldump -uroot -pmypassword --all-databases>test.sql more test.sql -- MySQL dump 10.13 Distrib 5.7.21, for linux-glibc2.12 (x86_64) -- -- Host: localhost Database: -- ----------------------------------…

获取字符串的在html页面上的宽度并且若文字过长则缩小字体填充

某个页面有这样一个需求:一个固定宽度的div,若文字过长,则缩小字体填充。 看到同事采用的是用php的GD库的imagettfbbox函数来计算文字的宽度。 imagettfbbox(float $size,float $angle,string $font_filename,string $string,array $options = []): array|false取得使用 Tru…

20222302 2024-2025-1 《网络与系统攻防技术》实验一实验报告

1.实验内容 本周学习内容1.熟练掌握了栈和堆的概念。 2.掌握了Linux的基本操作,如shell命令和编译器gcc、调试器gdb的使用。 3.掌握了缓冲区溢出的原理。实验任务 本次实验的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任…

github加速

Github一般用于Git的远程仓库,由于服务器位于国外,国内访问速度比较慢,为了提高访问速度,绕过DNS域名解析。 获取Github的IP地址按下ctrl+alt+T打开命令终端,输入: nslookup github.com 获取github.global.ssl.fastly.net的IP地址按下ctrl+alt+T打开命令终端,输入:…

Small Permutation Problem (Easy Version)

算法 考虑转化 每个点 \(p_i\) 在一个平面直角坐标系中表示为点 \((i, p_i)\) 于是转化为一个棋盘问题, 即每一个点不能在 同一行 / 同一列 \(a\) 数组的限制相当于在左下角为 \((0, 0)\), 右上角为\((i, i)\) 中的正方形中, 有 \(a_i\) 个棋子 于是在每一次加入的时候, 都只能…