我遇到了奇怪的问题,我无法理解。在主页中,我只有一个按钮可以导航到第二页并保存我的模型:
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;
}
}
没什么特别的。问题是,当我使用 Binding
和 x:Bind
时,我得到两个不同的输出,但最糟糕的是,每次新导航到同一页面后,属性的 getter(和 setter)在 x:Bind
中)被调用的次数越来越多:
旧页面仍然驻留在内存中并且仍然订阅属性,这是可以理解的。如果我们从页面返回后运行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)事件,仅 Index
的setter更改选择后调用属性。 getter 永远不会到达,因此您不会看到多个“获取值...”。
但是为什么getter没有被调用?
在此行上放置断点 -
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
您将看到 PropertyChanged
的值是 null
。所以Invoke
方法永远不会被触发。我怀疑这可能是 ComboBox
中的错误传统绑定(bind)设置为 OneWay
。每当您更改选择时,绑定(bind)都会被破坏,因此 PropertyChanged
是 null
。如果更改为使用x:Bind
,这个问题就消失了。
正如您所知,GC
仅在需要时收集废弃的页面实例。所以有时你会看到Index
无论您选择哪种绑定(bind)机制,都会在多个地方被引用。
保证 getter 和 setter 只被调用一次的一种方法是更改 NavigationCacheMode
你的第二个Page
至Enabled/Required
。这样做将确保页面的单个实例。
关于c# - 绑定(bind)和x :Bind problems with TwoWay mode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37217651/