有没有办法获取已编译绑定的UpdateSourceTrigger = PropertyChanged?

时间:2019-04-21 10:04:42

标签: c# xaml uwp windows-10-universal

我正在处理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)

  

对于我的测试,它运行良好。

这根本不适合我,正如我已经多次说过的那样,将UpdateSourceTriggerx: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

1 个答案:

答案 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();
    }
}