Is there any way to change menu selected item from ViewModel?

587 views Asked by At

I'm trying to change menu selected item from my ViewModel in my Xamarin.Forms application. How can I change that?

I've bind ListView SelectedItem property to field in my ViewModel, with mode "TwoWay". Also I used BeginInvokeOnMainThread and ContinueWith. To bind an event I created a behavior and bind Command to event. All the ways didn't change selected item.

<ListView
            x:Name="ListViewMenu"
            HasUnevenRows="True"
            ItemsSource="{Binding menuItems}"
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListView.Behaviors>
                <behaviors:EventToCommandBehavior
                    Command="{Binding command}"
                    Converter="{StaticResource SelectedItemConverter}"
                    EventName="ItemSelected" />
            </ListView.Behaviors>
private HomeMenuItem selectedItem { get; set; }
        public HomeMenuItem SelectedItem
        {
            get { return selectedItem; }
            set
            {
                selectedItem = value;
                this.OnPropertyChanged();
            }
        }
command = new AsyncRelayCommand((sender) => this.ItemSelected(sender).ContinueWith((arg) =>
            {
                HomeMenuItem menuItem = sender as HomeMenuItem;

                if(menuItem.Id != SelectedItem.Id)
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        SelectedItem = menuItems.Where(s => s.Id.Equals(menuItem.Id)).FirstOrDefault();
                    });
            }));

I expected to change selected item, from item Id 2 to Id 0 but this always stay on Id 2, even if SelectedItem variable is changed to Id 0. I mean visual representation don't change.

1

There are 1 answers

1
Leon On

I wrote a simple demo to update the menu selected item, you could refer to it.When I click the button the listview selectedItem will reback to the first one whatever I click the which one

enter image description here

There is MainPage.xml

   <StackLayout>
    <Button Command="{Binding UpdateCommand}"></Button>
    <ListView
        x:Name="ListViewMenu"
        HasUnevenRows="True"
        ItemsSource="{Binding menuItems}"
        SelectedItem="{Binding SelectedItem, Mode=TwoWay}">

        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout>
                        <Label Text="{Binding Name}" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>   
    </ListView>
</StackLayout>

MainPage.xml.cs

public partial class MainPage : ContentPage {

    public MainPageModelView model { get; set; }
    public MainPage()
    {
        InitializeComponent();



        model = new MainPageModelView();
        BindingContext = model;
    }


}

MainPageModelView.cs

public class MainPageModelView: INotifyPropertyChanged
{
    public ObservableCollection<HomeMenuItem> menuItems { set; get; }
    public event PropertyChangedEventHandler PropertyChanged;

    public MainPageModelView()
    {
        menuItems = new ObservableCollection<HomeMenuItem>();
        menuItems.Add(new HomeMenuItem() { Name = "Mr. Mono1", Id = 1 });
        menuItems.Add(new HomeMenuItem() { Name = "Mr. Mono2", Id = 2 });
        menuItems.Add(new HomeMenuItem() { Name = "Mr. Mono3", Id = 3 });
        menuItems.Add(new HomeMenuItem() { Name = "Mr. Mono4", Id = 4 });
    }

    private HomeMenuItem selectedItem { get; set; }
    public HomeMenuItem SelectedItem
    {
        get { return selectedItem; }
        set
        {
            selectedItem = value;
            this.OnPropertyChanged();
        }
    }


    Command _updateCommand;

    public Command UpdateCommand
    {
        get
        {
            return _updateCommand ?? (_updateCommand = new Command(ExecuteSaveCommand));
        }
    }
    void ExecuteSaveCommand()
    {
        Device.BeginInvokeOnMainThread(() =>
        {
               SelectedItem = menuItems[0];
        });
        //SelectedItem = menuItems.Where(s => s.Id.Equals(menuItem.Id)).FirstOrDefault();

    }
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this,
        new PropertyChangedEventArgs(propertyName));
    }
}