Привязки {x:Bind} (часто называемые скомпилированными привязками) используют сгенерированный код для достижения своих преимуществ. Во время загрузки XAML {x:Bind} преобразуется в то, что можно представить как объект привязки, и этот объект получает значение из свойства в источнике данных. Этот сгенерированный код можно найти в папке obj
с такими именами, как (для C#) <view name>.g.cs
.
Для вашего кода сгенерированный код будет выглядеть следующим образом:
// Update methods for each path node used in binding steps.
private void Update_(global::UWP.BlankPage3 obj, int phase)
{
if (obj != null)
{
if ((phase & (NOT_PHASED | DATA_CHANGED | (1 << 0))) != 0)
{
this.Update_ViewModel(obj.ViewModel, phase);
}
}
}
private void Update_ViewModel(global::UWP.ViewModel obj, int phase)
{
this.bindingsTracking.UpdateChildListeners_ViewModel(obj);
if (obj != null)
{
if ((phase & (NOT_PHASED | DATA_CHANGED | (1 << 0))) != 0)
{
this.Update_ViewModel_Text(obj.Text, phase);
}
}
}
...
private global::UWP.ViewModel cache_ViewModel = null;
public void UpdateChildListeners_ViewModel(global::UWP.ViewModel obj)
{
if (obj != cache_ViewModel)
{
if (cache_ViewModel != null)
{
((global::System.ComponentModel.INotifyPropertyChanged)cache_ViewModel).PropertyChanged -= PropertyChanged_ViewModel;
cache_ViewModel = null;
}
if (obj != null)
{
cache_ViewModel = obj;
((global::System.ComponentModel.INotifyPropertyChanged)obj).PropertyChanged += PropertyChanged_ViewModel;
}
}
}
Здесь я просто копирую какой-то метод, связанный с вашей проблемой. Из этого метода вы можете обнаружить, что перед обновлением слушателей TextBlock
или PropertyChanged
он проверяет, является ли ViewModel
null
. Если это null
, ничего не будет сделано. Таким образом, чтобы {x:Bind} работал, мы должны инициализировать ViewModel
перед загрузкой страницы. Именно по этой причине {x:Bind} не работает, когда вы инициализируете ViewModel
в событии Button.Click
.
Чтобы решить эту проблему, вы можете реализовать интерфейс INotifyPropertyChanged
для ViewModel
, как сказал Филип, чтобы сгенерированный код можно было уведомить об изменении ViewModel
(с null
на new ViewModel()
) и обновить пользовательский интерфейс.
Но я думаю, что вы можете просто инициализировать ViewModel
в конструкторе. Когда вы инициализируете ViewModel
, вы можете сначала установить ожидаемые свойства null
, например:
public MainPage()
{
ViewModel = new ViewModel() { Text = null };
this.InitializeComponent();
}
А затем обновите эти свойства, когда ваша дата будет готова. Таким образом, вы не сможете реализовать интерфейс INotifyPropertyChanged
на своей странице.
Помимо этого, есть еще один более дешевый способ: вы можете вызвать метод this.Bindings.Update();
, чтобы принудительно обновить привязки после инициализации ViewModel
следующим образом:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
ViewModel = new ViewModel();
ViewModel.Text = "x:Bind does not work";
this.Bindings.Update();
}
person
Jay Zuo
schedule
08.07.2016