将ButtonWPF应用程序中的Commands 绑定到VIEWMODEL类中的s 非常容易.我想为a实现类似的绑定TextBox.
我有一个TextBox和我需要将其绑定到Command一个触发,当我击中Enter而TextBox被聚焦.目前,我正在为KeyUp事件使用以下处理程序,但它看起来很丑......我不能把它放在我的VIEWMODEL课堂上.
private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Enter)
{
// your event handler here
e.Handled = true;
MessageBox.Show("Enter Key is pressed!");
}
}
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
所以在我正在做的这个特定的MVVM实现中,我需要几个命令.我真的厌倦了逐个实现ICommand类,所以我提出了一个解决方案,但我不知道它有多好,所以任何WPF专家的输入都将非常感激.如果你能提供更好的解决方案,那就更好了.
我所做的是一个ICommand类和两个代理,它们将一个对象作为参数,一个委托是void(对于OnExecute),另一个是bool(对于OnCanExecute).因此,在我的ICommand的构造函数(由ViewModel类调用)中,我发送了两个方法,并在每个ICommand方法上调用委托的方法.
它的效果非常好,但我不确定这是不是一个糟糕的方法,或者是否有更好的方法.下面是完整的代码,任何输入都会非常感激,甚至是负面的,但请建设性的.
视图模型:
public class TestViewModel : DependencyObject
{
public ICommand Command1 { get; set; }
public ICommand Command2 { get; set; }
public ICommand Command3 { get; set; }
public TestViewModel()
{
this.Command1 = new TestCommand(ExecuteCommand1, CanExecuteCommand1);
this.Command2 = new TestCommand(ExecuteCommand2, CanExecuteCommand2);
this.Command3 = new TestCommand(ExecuteCommand3, CanExecuteCommand3);
}
public bool CanExecuteCommand1(object parameter)
{
return true;
}
public void ExecuteCommand1(object parameter)
{
MessageBox.Show("Executing command 1");
}
public bool CanExecuteCommand2(object parameter)
{
return true;
}
public void ExecuteCommand2(object parameter)
{ …Run Code Online (Sandbox Code Playgroud) 让我们有一个Command绑定到自定义命令的按钮属性.
我什么时候应该实施ICommand,何时衍生出来RoutedCommand?我看到RoutedCommand实现了ICommand.
在哪种情况下我需要补充一个ICommand?那么MVVM模型呢?哪一种更适合这个目的?
考虑参考Josh Smith的文章WPF Apps with Model-View-ViewModel Design Pattern,特别是a的示例实现RelayCommand(图3).(无需阅读整篇文章以了解此问题.)
在一般情况下,我想实现是优秀的,但我有一个代表团的问题CanExecuteChanged订阅到CommandManager的RequerySuggested事件.各州的文件RequerySuggested:
由于此事件是静态的,因此它只会作为弱引用保留在处理程序中.侦听此事件的对象应该对其事件处理程序保持强引用,以避免它被垃圾回收.这可以通过拥有私有字段并在附加到此事件之前或之后将处理程序指定为值来实现.
然而,示例实现RelayCommand不会对订阅的处理程序维护任何此类:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
Run Code Online (Sandbox Code Playgroud)
RelayCommand客户端的漏洞,要求用户RelayCommand了解自己的实施CanExecuteChanged并维护一个实时参考?如果是这样,例如,修改实现RelayCommand类似于以下内容以减轻CanExecuteChanged订户的潜在过早GC 是否有意义:
// This event never actually fires. It's purely lifetime mgm't.
private event EventHandler canExecChangedRef;
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value; …Run Code Online (Sandbox Code Playgroud)我从Josh Smith的MVVM 教程中获得了以下代码.
任何人都可以快速解释这段代码实际上做了什么吗?
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
Run Code Online (Sandbox Code Playgroud)
我无法理解两件事:
CanExecuteChanged事件呢?CommandManager.RequerySuggested做什么的?上面的代码RelayCommand来自这里的Class .
调用CommandManager.InvalidateRequerySuggested()比我想要的更长时间才能生效(在UI控件被禁用之前1-2秒延迟).
我有一个系统,我将任务提交给基于后台线程的任务处理器.此提交发生在WPF UI线程上.
当这个提交发生时,管理我的后台线程的对象做了两件事:
它引发了一个"忙"事件(仍然在UI线程上),几个视图模型响应; 当他们收到这个事件时,他们IsEnabled会给自己设置一面旗帜false.我的视图中的控件(数据绑定到此属性)会立即显示为灰色,这正是我所期望的.
它通知我的WPF ICommand对象不应该允许它们执行(同样,仍然在UI线程上).因为没有像对象那样INotifyPropertyChanged的ICommand东西,我被迫调用CommandManager.InvalidateRequerySuggested()强制WPF重新考虑我的所有命令对象的CanExecute状态(是的,我实际上需要这样做:否则,这些控件都不会被禁用).但是,与第1项不同,我的按钮/菜单项/等使用ICommand对象在视觉上更改为禁用状态所需的时间要长得多,而对于IsEnabled手动设置其属性的UI控件则需要更长的时间.
问题是,从用户体验的角度来看,这看起来很糟糕 ; 我的一半控件立即显示为灰色(因为它们的IsEnabled属性设置为false),然后整整1-2秒后,我的控件的另一半跟随(因为他们的CanExecute方法最终被重新评估).
所以,我的问题的第一部分:
听起来很愚蠢,有没有办法让CommandManager.InvalidateRequerySuggested()我的工作更快?我怀疑没有.
很公平,我的问题的第2部分:
我如何解决这个问题?我希望我的所有控件都可以同时禁用.它只是看起来不专业而且很尴尬.有任何想法吗?:-)
Icommand包含两个方法和一个事件.
这两种方法的作用是明确的,但我无法理解事件所提供的内容ICommand.
活动何时CanExecuteChanged举起?
以下解释是在MSDN上,但我无法理解.
如果集中命令操作的命令管理器检测到命令源中的更改可能使已经引发但尚未由命令绑定执行的命令无效,则引发CanExecuteChanged.
你能用简单的语言解释一下吗?
谢谢......
我一直在研究这个问题大约一个小时,并查看了所有相关的SO问题.
我的问题很简单:
我有HomePageVieModel:
HomePageVieModel
+IList<NewsItem> AllNewsItems
+ICommand OpenNews
Run Code Online (Sandbox Code Playgroud)
我的加价:
<Window DataContext="{Binding HomePageViewModel../>
<ListBox ItemsSource="{Binding Path=AllNewsItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>
<Hyperlink Command="{Binding Path=OpenNews}">
<TextBlock Text="{Binding Path=NewsContent}" />
</Hyperlink>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Run Code Online (Sandbox Code Playgroud)
列表显示所有项目都很好,但对于我的生活,无论我尝试命令将无法工作:
<Hyperlink Command="{Binding Path=OpenNewsItem, RelativeSource={RelativeSource AncestorType=vm:HomePageViewModel, AncestorLevel=1}}">
<Hyperlink Command="{Binding Path=OpenNewsItem, RelativeSource={RelativeSource AncestorType=vm:HomePageViewModel,**Mode=FindAncestor}**}">
<Hyperlink Command="{Binding Path=OpenNewsItem, RelativeSource={RelativeSource AncestorType=vm:HomePageViewModel,**Mode=TemplatedParent}**}">
Run Code Online (Sandbox Code Playgroud)
我总是得到:
System.Windows.Data错误:4:无法找到带引用的绑定源.....
更新 我正在设置我的ViewModel吗?不认为这很重要:
<Window.DataContext>
<Binding Path="HomePage" Source="{StaticResource Locator}"/>
</Window.DataContext>
Run Code Online (Sandbox Code Playgroud)
我使用MVVMLight工具包中的ViewModelLocator类来完成这项工作.
我尝试做这样的事情:
<DataGrid Name="myGrid" ItemSource="{Binding Path=MyCollection}">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem
Command="{Binding RemoveRow}"
CommandParameter="{Binding ElementName=myGrid, Path=SelectedItem}">
</ContextMenu>
</DataGridContextMenu>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
但我总是得到null(我也试过SelectedIndex和SelectedValue)
如果我将以下参数传递给执行代码,它的工作原理如下:
<MenuItem Command="{Binding RemoveRow}" CommandParameter="1">
Run Code Online (Sandbox Code Playgroud) 我开始使用Metro风格的应用程序(我知道我们不应该将它称为Metro,但我永远不会记得它应该被称为...),而我正在实现一个DelegateCommand用于MVVM 的类.在WPF中,ICommand.CanExecuteChanged事件通常像这样实现:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
Run Code Online (Sandbox Code Playgroud)
但是这个CommandManager类在WinRT中不存在......还有别的东西吗?或者我们是否应该自己明确触发此事件?