‘壹’ 如何将WPF中的命令绑定到控件的双击事件处理程序
在视图编辑的界面,右键控件属性,看到那个黄色的闪电图标没,点击,里面就是这个控件可以相应的事件,然后你双击相应的事件,程序会为你自动生成函数头部的
‘贰’ WPF命令和事件之间的区别是什么
一般来说,你可以做几乎与事件与命令,它是处理用户交互只是一个不同的模式。
命令在WPF让您的命令处理程序的实现移动到楼内设有商务层。命令结合启用状态executation,所以一切都在发生。里德更多通过搜索MVVM模式。
命令更复杂的实施在第一,所以如果你的应用程序是小,你应该考虑的只是坚持到事件。
‘叁’ 什么时候使用事件和命令为WPF / MVVM
利用View里的IsEnable属性。 原理是这样的: 1、UI中的IsEnabled绑定VM中的属性 2、UI的后台代码中,注册IsEnableChange事件,在这个事件里,检测到传过来的值满足某个条件,即可触发Close()命令
‘肆’ WPF的自定义控件怎样添加Click事件
首先要给控件添加属性,然后为其添加事件,最后添加命令,具体步骤如下:
1,为控件添加属性(依赖属性,DependencyProperty)
正如下面的代码所示:
=
DependencyProperty.Register("Time",typeof(DateTime),typeof(ClockUserCtrl),
newFrameworkPropertyMetadata(DateTime.Now,newPropertyChangedCallback(TimePropertyChangedCallback)));
我们为控件(或者任何一个WPF类)添加的依赖属性都是"公开的","静态的","只读的",其命名方式是"属性名+Property",这是依赖属性一成不变的书写方式.对于依赖属性的注册可以在声明该属性时就调用DependencyProperty.Register()方法注册,也可以在其静态构造方法中注册.上面的DependencyProperty.Register方法的几个参数分别是:属性名(该属性名与声明的依赖属性名称"XXXProperty"相比仅仅是少了"Property"后缀,其它完全一样,否则在运行时会报异常),属性的数据类型,属性的拥有者的类型,元数据.
关于参数中传递的元数据:如果是普通的类则应该传递PropertyMetadata,如果是FrameworkElement则可以传递FrameworkPropertyMetadata,其中FrameworkPropertyMetadata中可以制定一些标记表明该属性发生变化时控件应该做出什么反应,比如某属性的变化会影响到该控件的绘制,那么就应该像这样书写该属性的元数据:new
FrameworkPropertyMetadata(defauleValue,
.AffectsRender);这样当该属性发生变化时系统会考虑重绘该控件.另外元数据中还保护很多内容,比如默认值,数据验证,数据变化时的回调函数,是否参与属性"继承"等.
然后,我们将该依赖属性包装成普通属性:
[Description("获取或设置当前日期和时间")]
[Category("CommonProperties")]
publicDateTimeTime
{
get
{
return(DateTime)this.GetValue(TimeProperty);
}
set
{
this.SetValue(TimeProperty,value);
}
}
GetValue和SetValue方法来自于DependencyObject类,其用于获取或设置类的某属性值.
注意:在将依赖属性包装成普通属性时,在get和set块中除了按部就班的调用GetValue和SetValue方法外,不要进行任何其它的操作.下面的代码是不恰当的:
[Description("获取或设置当前日期和时间")]
[Category("CommonProperties")]
publicDateTimeTime
{
get
{
return(DateTime)this.GetValue(TimeProperty);
}
set
{
this.SetValue(TimeProperty,value);
this.OnTimeUpdated(value);//Error
}
}
在以前这或许是很多人的惯用写法,但在WPF中,这样的写法存在潜在的错误,原因如下:我们知道继承于DependencyObject的类拥有GetValue和SetValue方法来获取或设置属性值,那为什么我们不直接使用该方法来获取或设置属性值,而要将其包装成普通的.NET属性呢,事实上在这里两种方式都是可以的,只不过包装成普通的.NET属性更符合.NET开发人员的习惯,使用GetValue和SetValue更像JAVA开发人员的习惯,但XAML在执行时似乎于JAVA开发人员一样,其不会调用.NET属性而是直接使用GetValue或SetValue方法,这样一来,我们写在get块和set块中的其它代码根本不会被XAML执行到.所以说,就上面的Time属性而言,C#(或其它)对该属性的调用不会出现任何问题,但该属性被用在XAML中时(比如在XAML对该属性进行数据绑定等),其set块中的this.OnTimeUpdated(value);语句不会被执行到.
那么,当Time属性发生变化时的确需要调用this.OnTimeUpdated(value);语句(因为该语句会引发时间被更新了的事件),还是在传递的依赖属性元数据做文章:
new FrameworkPropertyMetadata(DateTime.Now,new PropertyChangedCallback(TimePropertyChangedCallback)),我们为属性的变化指定了一个回调函数,当该属性变化时该回调函数就会被执行:
(DependencyObjectsender,)
{
if(sender!=null&&senderisClockUserCtrl)
{
ClockUserCtrlclock=senderasClockUserCtrl;
clock.OnTimeUpdated((DateTime)arg.OldValue,(DateTime)arg.NewValue);
}
}
2,为控件添加事件(传阅事件,RoutedEvent)
添加传阅事件的方法与添加依赖属性的方法很类似:
=
EventManager.RegisterRoutedEvent("TimeUpdated",
RoutingStrategy.Bubble,typeof(<DateTime>),typeof(ClockUserCtrl));
其支持方法EventManager.RegisterRoutedEvent()对应的几个参数分别为:事件名称,事件传阅的方式(向上传阅,向下传阅或不传阅),事件对应的EventHandler的类型,事件拥有者的类型)
然后将事件包装成普通的.NET事件:
[Description("日期或时间被更新后发生")]
publicevent<DateTime>TimeUpdated
{
add
{
this.AddHandler(TimeUpdatedEvent,value);
}
remove
{
this.RemoveHandler(TimeUpdatedEvent,value);
}
}
注意,与依赖属性一样,不要在add与remove块中添加除AddHandler与RemoveHandler以外的代码.
题外话,事件参数中的e.Handled=true并不是终止事件的传阅,这只是为事件做一个标记而已,以便在默认情况下的让那些事件处理函数在该标记为true的情况下不被调用,要为该标记为true的事件注册处理方法并让该方法得到执行,请使用AddHandler方法,并把最后一个参数handlerEventsToo设置为true,如下:
this.myInkCanvas.AddHandler(
InkCanvas.MouseLeftButtonDownEvent,
newMouseButtonEventHandler(
myInkCanvas_MouseLeftButtonDown),
true);
privatevoidmyInkCanvas_MouseLeftButtonDown(
objectsender,MouseButtonEventArgse)
{
//dosomething
}
然后编写惯用的OnXXX方法:
(DateTimeoldValue,DateTimenewValue)
{
<DateTime>arg=
new<DateTime>(oldValue,newValue,TimeUpdatedEvent);
this.RaiseEvent(arg);
}
3,为控件添加命令(Commands)
能为自定义控件添加如WPF内置控件一样的命令是一件很不错的事情(事实上这也是在CustomControl中降低界面和后台逻辑耦合度的一种方法,本系列随笔中的下一篇中将会具体谈谈).
WPF中内置的命令有两大类型:RoutedCommand以及RoutedUICommand,后者比前者多了一个Text属性用于在界面上自动本地化地显示该命令对应的文本,更多的可以参考WPF中的命令与命令绑定(一)以及WPF中的命令与命令绑定(二).
这里我们来定义一个命令,其功能是控件的语音报时.首先我们定义一个命令:
=newRoutedUICommand("Speak","Speak",typeof(ClockUserCtrl));
参数分别为命名的显示名称,命令的名称,命令的拥有者类型.
然后在控件的静态函数中定义一个命令绑定,该命令绑定定义了命令的具体细节:对应的命令是什么?其完成什么样的功能,当前环境下其能执行吗?
CommandBindingcommandBinding=newCommandBinding(SpeakCommand,newExecutedRoutedEventHandler(ExecuteSpeak),
(CanExecuteSpeak));
privatestaticvoidExecuteSpeak(objectsender,ExecutedRoutedEventArgsarg)
{
ClockUserCtrlclock=senderasClockUserCtrl;
if(clock!=null)
{
clock.SpeakTheTime();
}
}
(objectsender,CanExecuteRoutedEventArgsarg)
{
ClockUserCtrlclock=senderasClockUserCtrl;
arg.CanExecute=(clock!=null);
}
CanExecuteRoutedEventArgs的CanExecute属性用于指示当前命令是否可用,也就是说系统会不断地检视该命令与该命令的作用对象,并根据你所提供的条件来判断当前命令是否可用,比如文本框状态变为"只读"后,其"粘贴"命令将不可用,作用于该文本框的粘贴按钮会自动被禁用,反之则启用.
new ExecutedRoutedEventHandler(ExecuteSpeak)委托指定了当该命令被执行时所要完成的任务,这通过回调ExcuteSpeak函数来实现.
privatestaticvoidExecuteSpeak(objectsender,ExecutedRoutedEventArgsarg)
{
ClockUserCtrlclock=senderasClockUserCtrl;
if(clock!=null)
{
clock.SpeakTheTime();
}
}
privatevoidSpeakTheTime()
{
DateTimelocalTime=this.Time.ToLocalTime();
stringtextToSpeak="现在时刻,"+localTime.ToShortDateString()+","+localTime.ToShortTimeString()+",星期"+(int)localTime.DayOfWeek;
this.speecher.SpeakAsync(textToSpeak);
}
我们也可以为命令添加快捷键,这是通过InputBinding来实现的,其将命令与命令的快捷键关联起来,比如:
InputBindinginputBinding=newInputBinding(SpeakCommand,newMouseGesture(MouseAction.LeftClick));
CommandManager.RegisterClassInputBinding(typeof(ClockUserCtrl),inputBinding);
这样,当我们鼠标点击控件时就会引发控件的Speak命令,从而调用SpeakTheTime函数进行语音播报.
快捷键可以通过MouseGesture或KeyGesture来定义.
‘伍’ WPF怎么调用按钮触发事件的方法
可以的,只是没什么意义
this.txtDelay_KeyDown(txtDelay,newKeyEventArgs(
System.Windows.Input.Keyboard.PrimaryDevice,
PresentationSource.CurrentSources.OfType<PresentationSource>().First(),
Environment.TickCount,
Key.A));
‘陆’ VS菜鸟请教WPF编程中按钮事件的问题:Click和Click_1
出现 XXX_Click_1 的原因:
在设计器上点击按钮自动生成了 XXX_Click 函数,因某个操作 (删除控件后再次添加) 导致 XAML 中 Click="XXX_Click" 代码丢失,然后再次点击按钮而自动生成的。
解决办法很简单,在 XAML 代码编辑器中找到 XXX 然后将 Click="XXX_Click_1" 改成 "XXX_Click" 就可以了。也就是说,可以先定义事件处理函数,然后再为一个或多个控件指定。
RoutedEventArgs 和 EventArgs 不能随意替换。
Route 的意思就是路由,在 WPF 中引入了事件路由这一概念,举个例子比较好理解一点:
窗口中有一系列的控件 Grid\StackPanel\Button 等,
在 WinForm 中:当 Button 的 MouseMove 事件被触发时,其父级控件 (StackPanel、Grid、Form) 是不会触发 MouseMove 事件的。
WPF 中:会因路由概念的引入,导致 Button 的所有父级控件触发 MouseMove 事件,当然,前提是在代码中指定了事件函数。
所以,我们需要 RoutedEventArgs 这个参数,从 e.Source、e.OriginalSource 来确定该事件是由哪个子控件触发的。由于 WPF 控件是由 ControlTemplate 定义的,所以,单个控件也会需要事件路由来确定,该控件的模板中哪个元素引发了事件,从而精确处理控件事件。
‘柒’ wpf命令的好处,直接用方法不行吗搞的跟dos一样,感觉很奇特
wpf的命令用于那种需要主动询问的情况。比如,用户输入账户密码后登录按钮处于可用状态。传统的方式得用textChange事件来做。命令则不需要,命令让textbox主动发送状态来控制登录按钮的状态。是一种状态直接到状态的方式。
说到底,WPF的命令给了你除了方法以外的多的一个选择。
‘捌’ wpf窗体添加事件的地方在哪里
双击按钮。
在代码编辑器中,将随即创建 Click 事件处理程序,并且光标放置在该事件处理程序中。
将以下代码添加到事件处理程序中:C# code
MessageBox.Show("Event handler was created by " + "double-clicking the button.");
从“工具箱”中将第二个“Button”控件拖到 WPF 设计图面上,然后选择该按钮。
向 XAML 编辑器中的 Button 元素添加一个名为 Click 的属性,并将属性值设置为 ButtonOKClicked。此名称便是要指定给代码中的事件处理程序的名称。例如,该属性可以编写为:Click="ButtonOKClicked"。
右击设计器,然后单击“查看代码”。
向 Window1 类添加以下事件处理程序。单击按钮时,此代码将显示一条消息。
private void ButtonOKClicked(object sender, RoutedEventArgs e){MessageBox.Show("Event handler was created manually.");}
按 F5 运行程序。
当窗口出现时,单击按钮。
验证在单击每个按钮时消息框中显示的文本是否正确,然后关闭该应用程序。
‘玖’ WPF中的事件及冒泡事件和隧道事件的区别
冒泡事件表示事件从元素树向上到达根元素。这样您就可以在源元素的上方层级对象处理事件。例如,您可向嵌入的 Grid 元素附加一个 Button.Click 处理程序,而不是直接将其附加到按钮本身。气泡事件有指示其操作的名称(例如,MouseDown)。
隧道事件表示事件从根元素开始向下遍历元素树。这样上游元素就可以在事件到达源元素之前先行截取并进行处理。根据命名惯例,隧道事件带有前缀 Preview(例如 PreviewMouseDown)。
‘拾’ WPF DataGridTextColumn 怎么绑定一个事件命令
如果要实现类似点击header里面checkbox全选或反选的话,你要用DataGridTemplateColumn,然后在模板里设置UIElement,然后绑定Command或Event
如果要实现点击header排序的话,就需要设置CanUserSort="True"和SortMemberPath