Pod*_*elo 2 xaml eventtrigger commandparameter windows-runtime mvvmcross
我正在使用MvmmCross v3框架和Windows.UI.Interactivity开发 WinRT .
我想在TextChanged事件上使用带有EventTrigger的TextBox来启动Command.而且,我想在CommandParameter中使用textBox的文本.
所以我有这个代码
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding UpdateText}" CommandParameter="{Binding Text}"/>
</i:EventTrigger>
public ICommand UpdateText
{
get
{
return new MvxCommand<object>((textSearch) =>
{
// code...
});
}
}
Run Code Online (Sandbox Code Playgroud)
但我的textSearch参数等于"{Windows.UI.Xaml.Controls.TextChangedEventArgs}",所有这些属性都为NULL.
我试图在绑定中明确声明我的ElementName
CommandParameter="{Binding Path=Text, ElementName=tes}
Run Code Online (Sandbox Code Playgroud)
但它也失败了.
谢谢
你真的需要处理TextChanged事件吗?只需绑定到Text属性即可通知您更改:
<TextBox Text="{Binding TextValue, Mode=TwoWay}" />
Run Code Online (Sandbox Code Playgroud)
然后在视图模型中:
private string _textValue;
public string TextValue
{
get
{
return _textValue;
}
set
{
if (_textValue == value)
return;
_textValue = value;
OnTextChanged(value); // react to the changed value
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
如果你想Text从你的内部获得价值,你需要注意两件事Command:
首先,您需要修复CommandParameter绑定.通过使用,{Binding Text}您实际上尝试绑定到视图模型中的属性,即您首先需要将TextBox.Text属性绑定到相同的视图模型属性.正如你在评论中所说,这对你没有好处,因为你需要每次变化的信息,而不仅仅是失去焦点,所以你获得的价值不够新.
因此,正确的方法将是您的第二次尝试,即直接绑定到TextBox使用ElementName语法.不幸的是,触发器不是可视化树的一部分,因此它们无法访问XAML名称范围(您可以在此博客文章中阅读更多相关内容).您可以解决,通过使用NameScopeBinding从MVVMHelpers.Metro包:
<Behaviors:NameScopeBinding x:Key="MyTextBox"
Source="{Binding ElementName=MyTextBox}" />
Run Code Online (Sandbox Code Playgroud)
现在你可以使ElementName绑定工作:
<i:InvokeCommandAction Command="{Binding UpdateText}"
CommandParameter="{Binding Source.Text, Source={StaticResource MyTextBox}}"/>
Run Code Online (Sandbox Code Playgroud)
你还有第二个问题.Text您绑定的值仅在丢失焦点时更新,因此在处理TextChanged事件时您无法获得正确的值.解决方案是绑定TextBox自身:
<i:InvokeCommandAction Command="{Binding UpdateText}"
CommandParameter="{Binding Source, Source={StaticResource MyTextBox}}"/>
Run Code Online (Sandbox Code Playgroud)
然后在命令内Text直接获取属性TextBox:
private void OnUpdateText(object parameter)
{
var value = ((TextBox) parameter).Text;
// process the Text value as you need to.
}
Run Code Online (Sandbox Code Playgroud)
编辑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.
}
Run Code Online (Sandbox Code Playgroud)
甲清洁的解决方案将是把所述的WinRT特定代码转换成经由接口抽象的单独组件.您首先要在PCL库中创建一个接口:
public interface IUiService
{
string GetTextBoxText(object textBox);
}
Run Code Online (Sandbox Code Playgroud)
并修改视图模型以在构造函数中接受此接口:
public ViewModel(IUiService uiService)
{
_uiService = uiService;
}
Run Code Online (Sandbox Code Playgroud)
在命令处理程序中,您将使用接口中的方法:
private void OnUpdateText(object parameter)
{
var value = _uiService.GetTextBoxText(parameter);
// process the Text value as you need to.
}
Run Code Online (Sandbox Code Playgroud)
您将在WinRT库中实现该接口:
public class UiService : IUiService
{
public string GetTextBoxText(object textBox)
{
var typedTextBox = textBox as TextBox;
return typedTextBox.text;
}
}
Run Code Online (Sandbox Code Playgroud)
在应用程序中,您引用此库并将实现传递给视图模型:
var viewModel = new ViewModel(new UiService);
Run Code Online (Sandbox Code Playgroud)
我最喜欢的方法是不同的:每次触发事件时,我都会创建一个自动更新Behavior的Text属性TextChanged:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以将TextValue属性绑定到此行为,并对此属性setter中的更改作出反应,如此长答案的开头所述:
<TextBox>
<i:Interaction.Behaviors>
<b:TextChangedBehavior Text="{Binding TextValue, Mode=TwoWay}" />
</i:Interaction.Behaviors>
</TextBox>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4027 次 |
| 最近记录: |