c# - 绑定(bind)和x :Bind problems with TwoWay mode

标签 c# windows data-binding win-universal-app windows-10

我遇到了奇怪的问题,我无法理解。在主页中,我只有一个按钮可以导航到第二页并保存我的模型:

public class Model : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaiseProperty(string property) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));

    private int index = 0;
    public int Index
    {
        get { Debug.WriteLine($"Getting value {index}"); return index; }
        set { Debug.WriteLine($"Setting value {value}"); index = value; RaiseProperty(nameof(Index)); }
    }
}

public sealed partial class MainPage : Page
{
    public static Model MyModel = new Model();

    public MainPage()
    {
        this.InitializeComponent();
        SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
        SystemNavigationManager.GetForCurrentView().BackRequested += (s, e) => { if (Frame.CanGoBack) { e.Handled = true; Frame.GoBack(); } };
    }

    private void Button_Click(object sender, RoutedEventArgs e) => Frame.Navigate(typeof(BlankPage));
}

在第二页上只有ComboBox,它在SelectedIndex中具有双向绑定(bind):

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ComboBox SelectedIndex="{x:Bind MyModel.Index, Mode=TwoWay}">
        <x:String>First</x:String>
        <x:String>Second</x:String>
        <x:String>Third</x:String>
    </ComboBox>
</Grid>
public sealed partial class BlankPage : Page
{
    public Model MyModel => MainPage.MyModel;

    public BlankPage()
    {
        this.InitializeComponent();
        this.Unloaded += (s, e) => Debug.WriteLine("--- page unloaded ---");
        DataContext = this;
    }
}

没什么特别的。问题是,当我使用 Bindingx:Bind 时,我得到两个不同的输出,但最糟糕的是,每次新导航到同一页面后,属性的 getter(和 setter)在 x:Bind 中)被调用的次数越来越多:

enter image description here

页面仍然驻留在内存中并且仍然订阅属性,这是可以理解的。如果我们从页面返回后运行GC.Collect(),我们将从头开始。

但是如果我们使用旧的绑定(bind)单向和选择更改事件:

<ComboBox SelectedIndex="{Binding MyModel.Index, Mode=OneWay}" SelectionChanged="ComboBox_SelectionChanged">

与事件处理程序一起:

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.RemovedItems.Count > 0 && e.AddedItems.FirstOrDefault() != null)
        MyModel.Index = (sender as ComboBox).Items.IndexOf(e.AddedItems.FirstOrDefault());
}

然后它将“正常”工作——只有一个 getter 和 setter,无论我们之前导航到页面多少次。

所以我的主要问题是:

  • 单向 - 双向绑定(bind)的差异从何而来?
  • 考虑到单向绑定(bind)仅触发一次getter - 所描述的双向行为是期望/预期的吗?
  • 如果调用多个 getter/setter,您如何处理这种双向绑定(bind)?

您可以使用的工作示例 download from here .

最佳答案

实际上当你使用OneWay时与 SectionChanged 绑定(bind)事件,仅 Indexsetter更改选择后调用属性。 getter 永远不会到达,因此您不会看到多个“获取值...”

但是为什么getter没有被调用?

在此行上放置断点 -

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));

您将看到 PropertyChanged 的值是 null 。所以Invoke方法永远不会被触发。我怀疑这可能是 ComboBox 中的错误传统绑定(bind)设置为 OneWay 。每当您更改选择时,绑定(bind)都会被破坏,因此 PropertyChangednull 。如果更改为使用x:Bind ,这个问题就消失了。

正如您所知,GC仅在需要时收集废弃的页面实例。所以有时你会看到Index无论您选择哪种绑定(bind)机制,都会在多个地方被引用。

保证 getter 和 setter 只被调用一次的一种方法是更改​​ NavigationCacheMode你的第二个PageEnabled/Required 。这样做将确保页面的单个实例。

关于c# - 绑定(bind)和x :Bind problems with TwoWay mode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37217651/

相关文章:

c# - 会计数据库 - 存储贷方和借方?

c# - 使用 VsConnection WorkItemTrackingHttpClient 补丁通过 VSTS 客户端 API 添加父关系

c# - 在 VS 2022 .cs 页面中键入时出现重复字符

windows - 通过网络运行 VB6 exe - 它会在执行期间制作本地副本吗?

data-binding - 如何在一个表单中混合多个域对象?

c# - 如何查看 WCF 服务中的 JSON?

c - 在迷你过滤器驱动程序中使用 GetProcessImageFileName

php - XDebug 未加载到 PHP(Vista、Apache 模块)中

design-patterns - 数据绑定(bind)作为一种设计模式

c# - WPF TextBlock 文本绑定(bind)