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

问题描述 投票:1回答:1

我正在研究一个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做我需要的一切,不涉及任何代码。

谢谢!

更新:(回应Nico Zhu - MSFT的回答)

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

它根本不适合我,正如我已多次说过,使用UpdateSourceTriggerx:Bind是不可能的。它没有编译,属性在XAML编辑器中以红色显示,它就不存在。如果你说它适合你,我真的不知道你在哪里尝试。我目前最低目标是17763,我可以100%保证这不起作用。

Compiled Binding与{x:Bind}语法一起使用,而不是Classic Binding的{Binding}语法。

我很清楚这种差异,我已经多次提到过这个问题,我在这里提出了原始问题(也有代码片段)以及我的评论。

它仍然使用通知接口(如INotifyPropertyChanged)来监视更改

正如我所说,我也知道这一点。但同样,从这个问题来看,这根本不是问题所在。问题不在于从viewmodel到bound属性的更新,而是从绑定属性(在本例中为TextBox.Text)到viewmodel。

默认情况下,{x:Bind}是OneTime,而{Binding}则是OneWay。所以你需要为{x:Bind}声明绑定模式OneWay或TwoWay。

对不起,但我不得不说,在这一点上,我开始怀疑你是否真的读过我最初的问题。我知道这一点,事实上你可以在我的原始代码片段中看到我已经在我的两个绑定中使用了显式的Mode=TwoWay属性。

再一次,这根本不是问题所在。

重申:这里的问题是TextBox.Text属性默认为LostFocus触发器,并且UpdateSourceTrigger属性不可用于编译绑定。所以我想知道是否有一种方法可以在XAML中实现相同的编译绑定,而不必每次都手动创建一个TextChanged处理程序(如果不打算,如果你计划最终添加UpdateSourceTrigger)属性也可以编译绑定)。

旁注:我并不是说在这里听起来不尊重,我希望我们现在已经用我的问题解决了现有的误解。

更新#2:事实证明问题是由ReSharper插件引起的,该插件将UpdateSourceTrigger属性标记为编译绑定中的错误。我在这里开了一个问题:https://youtrack.jetbrains.com/issue/RSRP-474438

c# xaml uwp windows-10-universal
1个回答
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属性根本不可用。

对于我的测试,它运作良好。 Compiled Binding与{x:Bind}语法一起使用,而不是经典绑定的{Binding}语法。它仍然使用通知接口(如INotifyPropertyChanged)来监视更改,但{x:Bind}默认为OneTime,而{Binding}则是OneWay。所以你需要为OneWay声明绑定模式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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.