Home > Mobile >  Multibinding Converter not called in ItemsControl
Multibinding Converter not called in ItemsControl

Time:12-02

When SelectedItem value changes it does not trigger SelectedItemConverter.

I tried to use SetCurrentValue and InvalidateProperty and fiddled with attributes like NotifyOnSourceUpdated, UpdateSourceTrigger and Mode.

Sadly they do not work.

Perhaps I should add something in parent xaml to nudge it? Currently its:

   <local:Menu
            SelectedItem="{Binding SelectedMenuItem}"
            OnSelect="{Binding OnSelectCommand}" Items="{Binding MenuItems}"/>

Thanks for help.

control xaml

<UserControl>
 <UserControl.Resources>
        <vm:MockMenuViewModel x:Key="DesignViewModel"/>
        <cv:SelectedItemConverter x:Key="SelectedItemConverter"/>
    </UserControl.Resources>
    <ItemsControl
        d:DataContext="{Binding Source={StaticResource DesignViewModel}}"
        ItemsSource="{Binding Path=MenuItems, Mode=OneWay}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type MenuItem}">
                <Button Content="{Binding Name}"
                        Command="{Binding OnSelect, RelativeSource={RelativeSource AncestorType=UserControl}}"
                        CommandParameter="{Binding}">
                    <Button.IsEnabled>
                        <MultiBinding Converter="{StaticResource SelectedItemConverter}"
                                      NotifyOnSourceUpdated="True"
                                      NotifyOnTargetUpdated="True" Mode="OneWay">
                            <Binding Path="SelectedItem" UpdateSourceTrigger="PropertyChanged" Mode="OneWay"/>
                            <Binding Path="." Mode="OneWay"/>
                        </MultiBinding>
                    </Button.IsEnabled>
                </Button>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</UserControl>

control cs

 public partial class Menu : UserControl, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        public Menu()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
            "SelectedItem",
            typeof(MenuItem),
            typeof(Menu),
            new PropertyMetadata(null, OnSelectedItemChanged));

        public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
            "Items",
            typeof(IEnumerable<MenuItem>),
            typeof(Menu),
            new FrameworkPropertyMetadata(null));

        public static readonly DependencyProperty OnSelectProperty = DependencyProperty.Register(
            "OnSelect",
            typeof(ICommand),
            typeof(Menu),
            new PropertyMetadata(null, OnSelectChanged));


        public MenuItem SelectedItem
        {
            get => (MenuItem)GetValue(SelectedItemProperty);
            set
            {
                SetValue(SelectedItemProperty, value);
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Items)));
            }
        }

        public IEnumerable<MenuItem> Items
        {
            get => (IEnumerable<MenuItem>)GetValue(ItemsProperty);
            set => SetValue(ItemsProperty, value);
        }

        public ICommand OnSelect
        {
            get => (ICommand)GetValue(OnSelectProperty);
            set => SetValue(OnSelectProperty, value);
        }

        public static void OnSelectedItemChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            var menu = dependencyObject as Menu;

            if (menu == null)
            {
                return;
            }

            menu.InvalidateProperty(SelectedItemProperty);
            menu.InvalidateProperty(ItemsProperty);
        }

        public static void OnSelectChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            var menu = dependencyObject as Menu;

            if (menu == null)
            {
                return;
            }

            menu.SetCurrentValue(OnSelectProperty, eventArgs.NewValue);
        }
    }

CodePudding user response:

If you are trying to bind to the SelectedItem property of the parent Menu UserControl, you should specify a RelativeSource:

<Binding Path="SelectedItem"
    RelativeSource="{RelativeSource AncestorType=UserControl}"
    UpdateSourceTrigger="PropertyChanged" Mode="OneWay"/>
  • Related