我在我的Windows Phone 8.1中使用MVVM灯这里是代码
XAML
<TextBox Text="{Binding SearchText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="TextChanged">
<Core:InvokeCommandAction Command="{Binding SearchTextChanged}"></Core:InvokeCommandAction>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</TextBox>
Run Code Online (Sandbox Code Playgroud)
这是我的VM
private RelayCommand _searchTextChanged;
/// <summary>
/// Gets the SearchTextChanged.
/// </summary>
public RelayCommand SearchTextChanged
{
get
{
return _searchTextChanged
?? (_searchTextChanged = new RelayCommand(
() =>
{
LoadContents(this.SearchText);
}));
}
}
Run Code Online (Sandbox Code Playgroud)
每次更改文本时,SearchTextChanged命令都会正常触发,但SearchText属性中的文本未更新,它只减少一个字符.例如,如果文本框中的文本是A而不是SearchText包含null.如果文本框中的文本是'aaa'而不是SearchText中的文本只是'aa',则始终缺少最后一个字符.
有任何想法吗?
无论如何,我认为这是个问题.我正在使用RelayCommand,它使用两个委托来装饰ICommand.一个是_canExecute的Predicate,另一个是_execute方法的Action.
---背景动机 -
动机与单元测试ViewModel的WPF演示有关.一个常见的模式是我有一个具有ObservableCollection的ViewModel,我想要一个单元测试来证明该集合中的数据是我期望的一些源数据(也需要转换为ViewModel的集合).即使两个集合中的数据在调试器中看起来相同,但由于ViewModel的RelayCommand上的相等失败,看起来测试失败了.这是失败的单元测试的一个例子:
[Test]
public void Creation_ProjectActivities_MatchFacade()
{
var all = (from activity in _facade.ProjectActivities
orderby activity.BusinessId
select new ActivityViewModel(activity, _facade.SubjectTimeSheet)).ToList();
var models = new ObservableCollection<ActivityViewModel>(all);
CollectionAssert.AreEqual(_vm.ProjectActivities, models);
}
Run Code Online (Sandbox Code Playgroud)
---回到代表平等----
这是RelayCommand的代码 - 它基本上是对Josh Smith的想法的直接剽窃,我试图解决这个问题时添加了相等的实现:
public class RelayCommand : ICommand, IRelayCommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
/// <summary>Creates a new command that can always execute.</summary>
public RelayCommand(Action<object> execute) : this(execute, null) { }
/// <summary>Creates a new command which executes depending on the logic in the …Run Code Online (Sandbox Code Playgroud) 我有这个xaml代码:
<Window.InputBindings>
<KeyBinding Command="{Binding Path=KeyEnterCommand}" Key="Enter" />
</Window.InputBindings>
Run Code Online (Sandbox Code Playgroud)
这就是我的ViewModel中的代码:
private RelayCommand _keyEnterCommand;
public ICommand KeyEnterCommand
{
get
{
if (_keyEnterCommand == null)
{
_keyEnterCommand = new RelayCommand(param => ExecuteKeyEnterCommand());
}
return _keyEnterCommand;
}
}
public void ExecuteKeyEnterCommand()
{
// Do magic
}
Run Code Online (Sandbox Code Playgroud)
现在是我的问题,我怎样才能得到这个命令的发件人?
在我的ViewModel中,我实现了IDataErrorInfo接口(以及INotifyPropertyChanged)。输入验证按预期工作,我在那里没有问题。
我将此属性作为IDataErrorInfo的一部分,public string Error { get { return this[null]; } }据我了解,Error如果所有已验证的输入均通过验证,则应为空,因此我将此作为我的CanExecute方法传递
return !string.IsNullOrEmpty(Error);
Run Code Online (Sandbox Code Playgroud)
但是,我的“保存”按钮从未启用。我的CanExecuteChanged猜想是永远不会被触发。如果是这样,我应该在哪里以及如何触发它?
这是我的RelayCommand类。我尝试了其他实现方式,但结果相同。我认为它有效,因为如果不将CanExecute方法传递给构造函数,则会启用“保存”按钮。
public class RelayCommand : ICommand
{
private readonly Action execute;
private readonly Func<bool> canExecute;
public RelayCommand(Action execute, Func<bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Galasoft MVVMLight的RelayCommand执行RelayCommand(在我的CodeBehind中).
MainPage.xaml.cs中
public MainPage()
{
InitializeComponent();
DataContext = this;
MyCommand = new RelayCommand(Methode);
}
#region Commands
public RelayCommand MyCommand { get; private set; }
#endregion
private void Methode()
{
int i = 1;
}
Run Code Online (Sandbox Code Playgroud)
MainPage.xaml中:
<Button Command="{Binding MyCommand}"/>
Run Code Online (Sandbox Code Playgroud)
不幸的是,命令没有触发/该方法没有被调用.像ImageSource这样的其他绑定元素......工作正常.
我有一个代码片段如下:
XAML
...
<DataGrid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewKeyDown">
<mvvm:EventToCommand Command="{Binding KeyDownLocationDG}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
视图模型
public class A
{
public RelayCommand<KeyEventArgs> KeyDownLocationDG { get; set; }
public A()
{
KeyDownLocationDG = new RelayCommand<KeyEventArgs>(TestMethod);
App.processBarcodeData = new App.ProcessBarCodeData((barcode) =>
{
DoSomething();
// then I ONLY want to trigger KeyDownLocationDG command here
});
}
private void TestMethod(KeyEventArgs e)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
我也有一个 MainWindow.xaml 文件,有一个KeyPressed事件RawPresentationInput代码隐藏(MainWindow.xaml.cs)中对象。每次触发此事件时,我都会调用processBarcodeData委托。如果我在 DataGrid 上按下一个键,TestMethod它将立即执行,但我不想这样做,我想要的是让它只能在 DoSomething() 完成后运行。
有人能帮我吗?谢谢。
我正在将一个工具从 MVVM Light 4.0.3 迁移到 5.4.1,我发现最新的RelayCommand实现有一个非常奇怪的问题。
这是V4.0.3 中的旧实现:
这是V5.4.1 中的最新实现:
在我能够使用变量通过以下代码定义canExecute行为(启用按钮)之前:
public ICommand GetNewItemsFromDB { get; private set; }
private bool _IsActive;
public bool IsActive
{
get
{
return _IsActive;
}
set
{
if (_IsActive != value)
{
_IsActive = value;
this.RaisePropertyChanged(() => IsActive);
}
}
}
GetNewItemsFromDB = new RelayCommand(GetDataFromDB, () => { return IsActive == false; });
private void GetDataFromDB()
{
IsActive = true;
}
Run Code Online (Sandbox Code Playgroud)
之前的代码能够在 MVVM Light 4.0.3 中启用按钮而没有任何问题;然而,在最新的实现中总是被禁用,我添加了一些更改,因为有一个新的 …
我有一个Windows Phone 8应用程序,我有一个RelayCommand名为的实例DiscoverExpansionModulesCommand.我有一个Command属性绑定的按钮DiscoverExpansionModulesCommand.首次加载应用时,会正确启用或禁用该按钮.但是,当在页面上并且我想要更改命令是否可以执行时,方法会CanExecuteDiscoverExpansionModulesCommand()正确触发并返回正确的true或false值,但按钮不会反映它.为什么按钮没有更新它的UI?我在这里找到了另一篇关于这个问题的文章http://social.msdn.microsoft.com/Forums/en-US/silverlightarchieve/thread/48a341e4-f512-4c33-befd-b614404b4920/
我的ViewModel:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using MAL.Portable.Commands;
using MAL.Portable.Message;
using MAL.Portable.Model;
using System;
using System.Collections.Generic;
using System.Windows.Input;
namespace MAL.Portable.ViewModel
{
public class SettingsViewModel : ViewModelBase
{
// Define an observable collection property that controls can bind to.
private List<Setting> settings;
private String controllerUrl;
private String controllerPort;
private String temperature;
private Wifi wifi;
private Boolean connected;
private Boolean checkingConnection;
public SettingsViewModel()
{
DiscoverExpansionModulesCommand = new …Run Code Online (Sandbox Code Playgroud) relaycommand ×8
wpf ×6
c# ×3
mvvm-light ×3
mvvm ×2
xaml ×2
.net-4.5 ×1
binding ×1
button ×1
command ×1
delegates ×1
equality ×1
icommand ×1
key-bindings ×1