Xaml EventTrigger中的命令参数
我正在使用mvmmcrossv3框架和 我想要一个在事件TextChanged上带有EventTrigger的文本框,用于启动命令。还有,我想在CommandParameter中输入文本框的文本 所以我有这个密码Xaml EventTrigger中的命令参数,xaml,windows-runtime,mvvmcross,eventtrigger,commandparameter,Xaml,Windows Runtime,Mvvmcross,Eventtrigger,Commandparameter,我正在使用mvmmcrossv3框架和 我想要一个在事件TextChanged上带有EventTrigger的文本框,用于启动命令。还有,我想在CommandParameter中输入文本框的文本 所以我有这个密码 <i:EventTrigger EventName="TextChanged"> <i:InvokeCommandAction Command="{Binding UpdateText}" CommandParamete
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding UpdateText}" CommandParameter="{Binding Text}"/>
</i:EventTrigger>
public ICommand UpdateText
{
get
{
return new MvxCommand<object>((textSearch) =>
{
// code...
});
}
}
但它也失败了
谢谢您真的需要处理
TextChanged
事件吗?只需绑定到文本
属性即可通知您更改:
<TextBox Text="{Binding TextValue, Mode=TwoWay}" />
编辑:
如果要从命令中获取文本
值,有两件事需要注意:
首先,您需要修复命令参数
绑定。通过使用{Binding Text}
实际上是试图绑定到视图模型中的属性,即首先需要将TextBox.Text
属性绑定到同一视图模型属性。正如你在评论中所说的,这对你没有好处,因为你需要的是关于每一次改变的信息,而不仅仅是关于失去焦点的信息,所以你得到的价值不够及时
因此,正确的方法是第二次尝试,即使用ElementName
语法直接绑定到TextBox
。不幸的是,触发器不是可视化树的一部分,因此它们无法访问XAML名称范围(您可以在中了解更多信息)。您可以从以下位置使用NameScopeBinding
解决此问题:
您还有第二个问题。您绑定到的Text
值仅在焦点丢失时更新,因此在处理TextChanged
事件时无法获得正确的值。解决方案是绑定到文本框本身:
<i:InvokeCommandAction Command="{Binding UpdateText}"
CommandParameter="{Binding Source, Source={StaticResource MyTextBox}}"/>
编辑2:
要使上述代码与PCL中的视图模型一起工作,可以采取以下几种方法
最简单的技巧是使用反射。由于它在PCL中可用,因此您可以访问Text
属性并读取其值:
private void OnUpdateText(object parameter)
{
var textProperty = textSearch.GetType().GetProperty("Text");
var value = textProperty.GetValue(parameter, null) as string;
// process the Text value as you need to.
}
一个更干净的解决方案是将特定于WinRT的代码放入通过接口抽象的单独程序集中。首先在PCL库中创建一个接口:
public interface IUiService
{
string GetTextBoxText(object textBox);
}
并修改视图模型以在构造函数中接受此接口:
public ViewModel(IUiService uiService)
{
_uiService = uiService;
}
在命令处理程序中,您将使用接口中的方法:
private void OnUpdateText(object parameter)
{
var value = _uiService.GetTextBoxText(parameter);
// process the Text value as you need to.
}
您可以在WinRT库中实现该接口:
public class UiService : IUiService
{
public string GetTextBoxText(object textBox)
{
var typedTextBox = textBox as TextBox;
return typedTextBox.text;
}
}
在应用程序中,引用此库并将实现传递给视图模型:
private string _textValue;
public string TextValue
{
get
{
return _textValue;
}
set
{
if (_textValue == value)
return;
_textValue = value;
OnTextChanged(value); // react to the changed value
}
}
var viewModel = new ViewModel(new UiService);
我最喜欢的方法不同:我会创建一个行为
公开一个文本
属性,每次触发文本更改
事件时自动更新该属性:
public class TextChangedBehavior : Behavior<TextBox>
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(TextChangedBehavior),
new PropertyMetadata(null));
public string Text
{
get { return (string) GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TextChanged += OnTextChanged;
Text = AssociatedObject.Text;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.TextChanged -= OnTextChanged;
}
private void OnTextChanged(object sender, TextChangedEventArgs textChangedEventArgs)
{
Text = AssociatedObject.Text;
}
}
你能分享一个复制项目吗?我会尽快做的,在那里你可以看到GitHub项目谢谢你的回答,但是我真的需要改变文本,因为使用简单的绑定我们必须失去焦点才能抛出绑定。在我的例子中,它是在一个大列表中搜索某个项目,我真的需要在每次用户输入密钥时更新我的列表。@DevCrosser我更新了我的帖子,解释了你的绑定不起作用,并展示了如何使它按你的需要工作。非常感谢你的帮助,它只适用于一个简单的项目。但是我使用PCL内核,所以在我的ViewModels中不能使用TextBox类。在debug中,我看到我的参数带有文本属性wich,但正如我所说的,我不能在代码中强制转换它。我试图在NameScopeBinding中添加Path=Text,但在输入文本时,输出延迟了一个字母。@DevCrosser我添加了一些建议,以便使用PCL使一切正常工作。我不愿意将MVVMHelpers添加到我的项目中,只是为了尝试一下,但它确实起了作用,我的CommandParameter引用了一个元素名。我使用了通用的MVVMHelpers包,而不是Win 8.1特定包,以及您的CommandParameter=“{Binding Source.Text,Source={StaticResource MyTextBox}}”
。我的控件名是userControl
,我得到了一个名为BumpAmount
的依赖属性:
private void OnUpdateText(object parameter)
{
var value = _uiService.GetTextBoxText(parameter);
// process the Text value as you need to.
}
public class UiService : IUiService
{
public string GetTextBoxText(object textBox)
{
var typedTextBox = textBox as TextBox;
return typedTextBox.text;
}
}
var viewModel = new ViewModel(new UiService);
public class TextChangedBehavior : Behavior<TextBox>
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(TextChangedBehavior),
new PropertyMetadata(null));
public string Text
{
get { return (string) GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TextChanged += OnTextChanged;
Text = AssociatedObject.Text;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.TextChanged -= OnTextChanged;
}
private void OnTextChanged(object sender, TextChangedEventArgs textChangedEventArgs)
{
Text = AssociatedObject.Text;
}
}
<TextBox>
<i:Interaction.Behaviors>
<b:TextChangedBehavior Text="{Binding TextValue, Mode=TwoWay}" />
</i:Interaction.Behaviors>
</TextBox>