Любопытная разница в поведении между скомпилированным и регулярным связыванием
Я пытаюсь создать MenuFlyout с ToggleMenuFlyoutItems, где один и только один переключатель проверяется в любой момент. Переключатели соответствуют ToggleViewModels, связывая свойство IsChecked переключателя со свойством IsSelected объекта ToggleViewModel. Поскольку я хочу снять флажок с ранее проверенного переключателя всякий раз, когда проверяется новый переключатель, я передаю настройку свойства IsSelected в MainViewModel, который содержит коллекцию ToggleViewModels.
Кнопка с выпадающим списком, определенным в MainPage.xaml
<Button Content="Asdf">
<Button.Flyout>
<MenuFlyout>
<ToggleMenuFlyoutItem
Text="{x:Bind _viewModel.ToggleCollection[0].Name}"
IsChecked="{x:Bind _viewModel.ToggleCollection[0].IsSelected, Mode=TwoWay}" />
<ToggleMenuFlyoutItem
Text="{x:Bind _viewModel.ToggleCollection[1].Name}"
IsChecked="{x:Bind _viewModel.ToggleCollection[1].IsSelected, Mode=TwoWay}" />
<ToggleMenuFlyoutItem
Text="{x:Bind _viewModel.ToggleCollection[2].Name}"
IsChecked="{x:Bind _viewModel.ToggleCollection[2].IsSelected, Mode=TwoWay}" />
</MenuFlyout>
</Button.Flyout>
</Button>
MainPageViewModel:
public class MainViewModel : BindableBase
{
public MainViewModel()
{
ToggleCollection = new ObservableCollection<ToggleViewModel>();
var selectToggleAction = new Action<ToggleViewModel>(param => SetToggleSelection(param));
for (int i = 0; i < 3; i++)
{
ToggleCollection.Add(new ToggleViewModel($"Item {i}", selectToggleAction));
}
}
public ObservableCollection<ToggleViewModel> ToggleCollection { get; private set; }
private void SetToggleSelection(ToggleViewModel toggle)
{
var selectedToggle = ToggleCollection.SingleOrDefault(t => t.IsSelected);
if (selectedToggle != toggle)
{
selectedToggle?.SetSelection(false);
toggle.SetSelection(true);
}
}
}
ToggleViewModel:
public class ToggleViewModel : BindableBase
{
private Action<ToggleViewModel> _selectToggleAction;
private bool _isSelected;
public ToggleViewModel(string name, Action<ToggleViewModel> action)
{
Name = name;
_selectToggleAction = action;
}
public string Name { get; set; }
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_selectToggleAction(this);
base.OnPropertyChanged();
}
}
}
public void SetSelection(bool selected)
{
_isSelected = selected;
base.OnPropertyChanged("IsSelected");
}
}
Теперь весь код выше работает очень хорошо. Проблема возникает, когда я пытаюсь использовать обычные привязки вместо скомпилированных:
<ToggleMenuFlyoutItem
Text="{Binding ToggleCollection[0].Name}"
IsChecked="{Binding ToggleCollection[0].IsSelected, Mode=TwoWay}" />
Привязывая свойства, подобные этим, я внезапно могу снять флажок с текущего проверенного переключателя, чтобы ни одно из них не было выбрано. Это происходит из-за того, что средство получения свойства IsSelected не вызывается, когда я поднимаю OnPropertyChanged в установщике свойства IsSelected (причина использования регулярных привязок заключается в том, что я хочу динамически создавать переключатели в коде позади, но чтобы проиллюстрировать проблему XAML работает так же хорошо).
Может кто-нибудь объяснить мне, почему {x:Bind}
в этом случае работает, но не {Binding}
?