简体   繁体   English

如何在 xamarin.forms 中的 viewcell 中设置按钮以从内容页面 viewmodel 调用命令?

[英]How do I set a button in viewcell in xamarin.forms to call a command from the content page viewmodel?

In the GroceryListViewModel is a command called ButtonClicked that I would like a button to use.在 GroceryListViewModel 中有一个名为 ButtonClicked 的命令,我想使用一个按钮。 However, that button is located in the ViewCell of a ListView and can't access the command.但是,该按钮位于 ListView 的 ViewCell 中,无法访问该命令。 What I'm currently doing causes the command to be called every time the ViewCell loads and whenever the ViewCell is clicked on.我目前正在做的事情导致每次加载 ViewCell 以及单击 ViewCell 时都会调用该命令。 The button in question doesn't work for a few of the ViewCells at the top of the list but works further down the list.有问题的按钮对列表顶部的一些 ViewCell 不起作用,但在列表的下方起作用。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:VM="clr-namespace:FoodLifeApp.ViewModels"
             mc:Ignorable="d"
             x:Class="FoodLifeApp.PageViews.GroceryListPage"
             x:Name="GroceryList">
    <ContentPage.BindingContext >
        <VM:GroceryListViewModel x:Name="VMGroceryList"/>
    </ContentPage.BindingContext>
    <ListView x:Name="MyListView"
            ItemsSource="{Binding DisplayList}"
            IsGroupingEnabled="True"
            HasUnevenRows="True"
            CachingStrategy="RecycleElement">
        <ListView.Header >
            <SearchBar Placeholder="Search" 
                       Text="{Binding SearchText}" 
                       HeightRequest="40" 
                       SearchCommand="{Binding Search}"
                       />
        </ListView.Header>
        <ListView.GroupHeaderTemplate >
            <DataTemplate>
                <ViewCell Height="20">
                    <Label Text="{Binding Heading}"  
                           BackgroundColor="LightGray" 
                           FontAttributes="Bold" 
                           HorizontalTextAlignment="Center" 
                           VerticalTextAlignment="Center" />
                </ViewCell>
            </DataTemplate>
        </ListView.GroupHeaderTemplate>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell Height="40">
                    <StackLayout Orientation="Horizontal" >
                        <Label Text="{Binding ProductName}" 
                               VerticalTextAlignment="Center"/>
                        <Label Text="{Binding ProductSize}" 
                               FontSize="10" 
                               VerticalTextAlignment="Center"/>
                        <Button ImageSource="{Binding ButtonImage}" 
                                     BackgroundColor="Transparent"
                                     CommandParameter="{Binding ProductName}" 
                                     Command="{Binding Path=ButtonClicked, Source={x:Reference VMGroceryList}}" />
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>
class GroceryListViewModel : ContentPage, INotifyPropertyChanged
    {
        private List<ShoppingList> _ListOfShoppingList;
        private List<ShoppingList> _SearchResults;
        private String _searchText;
        private Command searchCommand;
        public event PropertyChangedEventHandler PropertyChanged;

        public GroceryListViewModel()
        {
            var meatList = new ShoppingList()
            {
                new ShoppingItem() { ProductName="Beef", ProductQuantity=7},
                new ShoppingItem() { ProductName="Chicken", ProductQuantity=3},
                new ShoppingItem() { ProductName="Pork", ProductQuantity=5},
            };
            meatList.Heading = "Meats";
            var fruitList = new ShoppingList()
            {
                new ShoppingItem() { ProductName="Apples", ProductQuantity=12},
                new ShoppingItem() { ProductName="Bananas", ProductQuantity=6},
                new ShoppingItem() { ProductName="Peaches", ProductQuantity=4},
            };
            fruitList.Heading = "Fruits";
            var vegetableList = new ShoppingList()
            {
                new ShoppingItem() { ProductName="Corn", ProductQuantity=8},
                new ShoppingItem() { ProductName="Potatoes", ProductQuantity=9},
                new ShoppingItem() { ProductName="Green Beans", ProductQuantity=8},
                new ShoppingItem() { ProductName="Broccoli", ProductQuantity=1}
            };
            vegetableList.Heading = "Vegetables";
            DisplayList = new List<ShoppingList>()
            {
                meatList,
                fruitList,
                vegetableList
            };
            Search = new Command(async () =>
            {
                ShoppingList tempList = new ShoppingList();
                tempList.Heading = "Search Results";
                RestHelper restH = new RestHelper();
                JObject sRes = await restH.GetKroger(SearchText);
                foreach (var currItem in sRes["data"])
                {
                    tempList.Add(new ShoppingItem() { ProductName = currItem["description"].ToString(), ProductQuantity = 0, ProductSize = currItem["items"][0]["size"].ToString()});
                }
                DisplayList = new List<ShoppingList>() { tempList };
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("DisplayList"));

            });
        }

        public List<ShoppingList> DisplayList
        {
            get
            {
                if (IsSearchingBool.IsSearchingInstance.getIsSearching())
                {
                    Debug.WriteLine("RETURNING SEARCH RESULTS");
                    return _SearchResults;
                } else
                {
                    Debug.WriteLine("RETURNING GROCERY LIST");
                    return _ListOfShoppingList;
                }
            }
            set
            {
                if (IsSearchingBool.IsSearchingInstance.getIsSearching())
                {
                    _SearchResults = value;
                } else
                {
                    _ListOfShoppingList = value;
                }
                base.OnPropertyChanged();
            }
        }

        public String SearchText
        {
            set
            {
                if (value.Length == 0 && IsSearchingBool.IsSearchingInstance.getIsSearching() == true)
                {
                    IsSearchingBool.IsSearchingInstance.setIsSearching(false);
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("DisplayList"));
                } else if (value.Length > 0 && IsSearchingBool.IsSearchingInstance.getIsSearching() == false)
                {
                    IsSearchingBool.IsSearchingInstance.setIsSearching(true);
                    Search.CanExecute(this);
                }
                _searchText = value;
                base.OnPropertyChanged();
            }
            get
            {
                return _searchText;
            }
        }

        public ICommand Search
        {
            get; private set; 
        }

        public ICommand ButtonClicked
        {
            get
            {
                Debug.WriteLine("in button clicked");
                if (IsSearchingBool.IsSearchingInstance.getIsSearching())
                {
                    Debug.WriteLine("is searching");
                    return new Command<String>((itemName) => {
                        Debug.WriteLine(itemName);
                        Debug.WriteLine(_SearchResults[0].ToString());
                        Debug.WriteLine(_ListOfShoppingList[0].ToString());
                        ShoppingItem temp = _SearchResults[0].Find(x => x.ProductName.Equals(itemName));
                        _SearchResults[0].Remove(temp);
                        _ListOfShoppingList[0].Add(temp);
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("DisplayList"));
                    });
                } else
                {
                    Debug.WriteLine("Not searching");
                    return new Command(() => { });
                }
            }
        }
    }

Your button Command binding looks wrong您的按钮Command绑定看起来不对

Try尝试

Command="{Binding Path=BindingContext.ButtonClicked, Source={x:Reference MyListView}}" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM