我正在处理UWP应用程序,我意识到UpdateSourceTrigger
控件的默认TextBox
模式(LostFocus
)在使用编译绑定时无法更改
这意味着每当我要为TextBox
更新绑定时,都必须使用所有这些重复的样板:
<TextBox
Text="{x:Bind ViewModel.Title, Mode=TwoWay}"
TextChanged="TextBox_OnTextChanged"/>
private void TextBox_OnTextChanged(object sender, TextChangedEventArgs e)
{
ViewModel.Title = ((TextBox)sender).Text;
}
现在,这还不错,但是每次使用TextChanged
时都要记住要创建TextBox
处理程序,这很烦人并且容易出错。
这在经典的绑定中可以很好地工作:
<TextBox Text="{Binding Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
但是,当然,这里会有usinc经典绑定的额外开销(涉及运行时反射等)。
是否有办法获得与UpdateSourceTrigger=PropertyChanged
相同的行为?我会写一个自定义的附加属性来设置一切,只要我可以直接从XAML完成我需要做的所有事情,而无需编写任何代码,就可以了。
谢谢!
更新:(回应MSFT的回答Nico Zhu)
对于我的测试,它运行良好。
这根本不适合我,正如我已经多次说过的那样,将UpdateSourceTrigger
与x:Bind
一起使用是不可能的。它不会编译,该属性在XAML编辑器中以红色显示,只是不存在。我真的不知道您在哪里尝试,如果您说它对您有用。我目前的最低目标是17763,我可以100%保证不起作用。
编译绑定与{x:Bind}语法一起使用,与经典绑定的{Binding}语法相反。
我很清楚两者之间的区别,我已经在这里的原始问题(也有代码段)以及我的评论中多次提到了这一点。
它仍然使用通知接口(例如INotifyPropertyChanged)来监视更改
正如我所说,我也知道这一点。但是同样,从这个问题出发,这根本不是问题。问题不是,是从视图模型到绑定属性的更新,而是从绑定属性的更新(本例中为TextBox.Text)。 >到视图模型。
{x:Bind}
在默认情况下是OneTime,而{Binding}是OneWay。因此您需要为{x:Bind}声明绑定模式OneWay或TwoWay。
很抱歉,但是现在我不得不说,我开始想知道您是否真的读过我最初的问题。我知道这一点,实际上您可以在 both 中看到我的原始代码段,我已经在两个绑定中都使用了显式的Mode=TwoWay
属性。
再一次,这根本不是问题所在。
重申一下:这里的问题是TextBox.Text
属性默认为LostFocus
触发器,并且UpdateSourceTrigger
属性不可用于已编译的绑定。因此,我想知道是否有一种方法可以通过仅在XAML中使用已编译的绑定来实现相同目的,而不必每次都手动创建TextChanged
处理程序(如果没有,如果您打算最终也将UpdateSourceTrigger
属性也添加到已编译的绑定中。
旁注:我并不是故意在这里不尊重别人,我希望我们现在已经用我的问题解决了现有的误解。
更新#2:证明此问题是由ReSharper插件引起的,该插件将UpdateSourceTrigger
属性标记为已编译绑定中的错误。
我在这里为此打开了一个问题:https://youtrack.jetbrains.com/issue/RSRP-474438
答案 0 :(得分:0)
请查看UpdateSourceTrigger
文档。
UpdateSourceTrigger的默认值为Default
。和
使用来自使用绑定的依赖项属性的默认行为。在Windows运行时中,其求值与PropertyChanged
的值相同。如果您使用Text="{x:Bind ViewModel.Title, Mode=TwoWay}"
,则标题将在文本更改时更改。我们甚至不需要在TextChanged
甚至处理程序中修改viewmode。
前提是我们需要像下面这样实现INotifyPropertyChanged
。
public class HostViewModel : INotifyPropertyChanged
{
private string nextButtonText;
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public HostViewModel()
{
this.NextButtonText = "Next";
}
public string NextButtonText
{
get { return this.nextButtonText; }
set
{
this.nextButtonText = value;
this.OnPropertyChanged();
}
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
// Raise the PropertyChanged event, passing the name of the property whose value has changed.
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
有关更多详细信息,请参阅Data binding in depth文档。
更新
<TextBox Text="{x:Bind Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
根本不编译,因为我说过UpdateSourceTrigger
属性在使用编译绑定时根本不可用。
对于我的测试,它运行良好。与经典绑定的{x:Bind}
语法相反,编译绑定与{Binding}
语法一起使用。它仍然使用通知界面(例如INotifyPropertyChanged
)来监视更改,但是{x:Bind}
在默认情况下是OneTime,而{Binding}
是OneWay。因此您需要为OneWay
声明绑定 Mode TwoWay
或{x:Bind}
。
Xaml
<StackPanel Orientation="Vertical">
<TextBox Text="{x:Bind Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{x:Bind Title, Mode=OneWay}" /> <!--declare bind mode-->
</StackPanel>
背后的代码
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string _title;
public string Title
{
get
{
return _title;
}
set
{
_title = value;
OnPropertyChanged();
}
}