单独的ListView模板xamarin中的按钮BindingContext

时间:2018-08-24 16:36:48

标签: listview xamarin xamarin.forms icommand

因此,我正在xamarin上开发应用程序 我尝试包括单独的DataTemplate。 我的listView引用了另一个ContentView,其中有一个TempleView用于listview,但是该按钮在View模型中未调用Icommand。

对不起,我的英语不太好,但是我需要帮助 tks。

                  <ListView                     
                        ItemsSource="{Binding ItensOrder}"                                   
                        x:Name="PartListView"                          
                        HasUnevenRows ="True"
                        RowHeight="110"                  
                        IsPullToRefreshEnabled= "{Binding IsNotBusy}"          
                        CachingStrategy="RecycleElement"
                        IsVisible="{Binding IsNotBusy}"    
                        AbsoluteLayout.LayoutFlags="All" 
                        AbsoluteLayout.LayoutBounds="0,0,1,1">
                        <ListView.SeparatorColor>
                            <OnPlatform x:TypeArguments="Color" iOS="{StaticResource ListSeparator}" Android="Transparent"/>
                        </ListView.SeparatorColor>
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell StyleId="disclosure">
                                    <local:BasketEquipamentPartCell/>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>

模板(BasketEquipamentPartCell)代码:

     <AbsoluteLayout HorizontalOptions="StartAndExpand">
                <Grid Padding="16" ColumnSpacing="16">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width=".5*"/>
                        <ColumnDefinition Width=".1*"/>
                        <ColumnDefinition Width=".1*"/>
                        <ColumnDefinition Width=".1*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>

                    <Label VerticalOptions="Center"  Grid.Column="0" Grid.Row="0"  HorizontalOptions="StartAndExpand"  Text="Código Modelo:"/>
                    <Label VerticalOptions="Center" Grid.Column="0" Grid.Row="1"   HorizontalOptions="StartAndExpand" Text="Cópias Por Ciclo:"/>
                    <Label VerticalOptions="Center" Grid.Column="0" Grid.Row="2"   HorizontalOptions="StartAndExpand" Text="Descrição Produto:"/>
                    <Label VerticalOptions="Center" Grid.Column="0" Grid.Row="3"   HorizontalOptions="StartAndExpand" Text="Amount:"/>

                    <Label VerticalOptions="Center" Grid.Column="1" Grid.Row="0"  Grid.ColumnSpan="3" Text="{Binding EquipamentPart.EquipmentModel}"/>
                    <Label VerticalOptions="Center" Grid.Column="1" Grid.Row="1"  Grid.ColumnSpan="3"  Text="{Binding EquipamentPart.LifeCycle}"/>
                    <Label VerticalOptions="Center" Grid.Column="1" Grid.Row="2"  Grid.ColumnSpan="3" Text="{Binding EquipamentPart.Description}"/>
                    <Button Text="+"  Grid.Column="1" Grid.Row="3" 
                                BackgroundColor="DodgerBlue"
                                TextColor="White"
                                WidthRequest="100"
                                 />
                    <Label VerticalOptions="Center" Grid.Column="2" Grid.Row="3" Text="{Binding Amount}" HorizontalOptions="CenterAndExpand"/>
                    <Button Text="-"  Grid.Column="3" Grid.Row="3" 
                                BackgroundColor="DarkGreen"
                                Command="{Binding BindingContext.removeItemOder}"                                  
                                TextColor="White"
                                WidthRequest="100"                                   
                                 />
                    <Button Text="Delete" Grid.ColumnSpan="4" Grid.Column="0" Grid.Row="4" 
                                BackgroundColor="DarkRed"                                    
                                TextColor="White"
                                WidthRequest="100"
                                Command="{Binding Source={x:Reference BasketEquipamentPartCellPage}, Path=BindingContext.removeItemOder}" 
                                CommandParameter="{Binding .}"/>
                </Grid>
            </AbsoluteLayout>`

我在viewmodel中的命令

      public class BasketEquipamentPartViewModel : ViewModelBase
{
    public ObservableCollection<OrderItem> ItensOrder { get; set; }

    INavigation navigation;
    private ICommand _removeItemOder, _addItemOder, _deleteOrder;

    private uint _badgeCount;
    public uint BadgeCount
    {
        get { return _badgeCount; }
        set
        {
            _badgeCount = value;
            OnPropertyChanged("BadgeCount");
        }
    }


    public ICommand removeItemOder =>
      _removeItemOder ?? (_removeItemOder = new Command<OrderItem>(async (item) => await removeItemOderCommandAsync(item)));
    public ICommand deleteOrder =>
      _deleteOrder ?? (_deleteOrder = new Command<OrderItem>(async (item) => await deleteOrderCommandAsync(item)));
    public ICommand addItemOder =>
      _addItemOder ?? (_addItemOder = new Command<OrderItem>(async (item) => await addItemOderCommandAsync(item)));


    public BasketEquipamentPartViewModel(INavigation navigation )
    {
        ItensOrder = new ObservableCollection<OrderItem>();            
        this.navigation = navigation;

        CreateMessaging();

    }
    public void CreateMessaging()
    {
        MessagingCenter.Unsubscribe<EquipamentPartOrderViewModel, EquipamentPart>(this, MessageKeys.AddProduct);
        MessagingCenter.Subscribe<EquipamentPartOrderViewModel, EquipamentPart>(this, MessageKeys.AddProduct, async (sender, arg) =>
        {
            BadgeCount++;

            await AddEquipamentPartAsync(arg);
        });
    }
    private async Task AddEquipamentPartAsync(EquipamentPart item)
    {

        if (ItensOrder.Where(x => x.EquipamentPart.Equals(item)).Count() > 0)
        {            
           var index= ItensOrder.IndexOf(ItensOrder.Where(c => c.EquipamentPart == item).FirstOrDefault());
            var i = new OrderItem(ItensOrder[index].EquipamentPart, ItensOrder[index].Amount+1);               

            ItensOrder.RemoveAt(index);
            ItensOrder.Insert(index,i);

        }
        else
        ItensOrder.Add(new OrderItem(item, 1));          
        OnPropertyChanged("ItensOrder");
    }

    private async Task addItemOderCommandAsync(OrderItem item)
    {
        if (ItensOrder.Where(x => x.EquipamentPart.Equals(item.EquipamentPart)).Count() > 0)
        {
            var index = ItensOrder.IndexOf(ItensOrder.Where(c => c.EquipamentPart == item.EquipamentPart).FirstOrDefault());
            var i = new OrderItem(ItensOrder[index].EquipamentPart, ItensOrder[index].Amount + 1);
            ItensOrder.RemoveAt(index);
            ItensOrder.Insert(index, i);
            BadgeCount++;
        }
    }
    private async Task removeItemOderCommandAsync(OrderItem item)
    {
        if (ItensOrder.Where(x => x.EquipamentPart.Equals(item.EquipamentPart)).Count() > 0)
        {
            var index = ItensOrder.IndexOf(ItensOrder.Where(c => c.EquipamentPart == item.EquipamentPart).FirstOrDefault());
            if (ItensOrder[index].Amount > 1)
            {
                var i = new OrderItem(ItensOrder[index].EquipamentPart, ItensOrder[index].Amount - 1);
                ItensOrder.RemoveAt(index);
                ItensOrder.Insert(index, i);
                BadgeCount--;
            }

        }
    }
    private async Task deleteOrderCommandAsync(OrderItem item)
    {
        if (ItensOrder.Where(x => x.EquipamentPart.Equals(item.EquipamentPart)).Count() > 0)
        {
            var index = ItensOrder.IndexOf(ItensOrder.Where(c => c.EquipamentPart == item.EquipamentPart).FirstOrDefault()); 
            ItensOrder.RemoveAt(index);
            BadgeCount-=item.Amount;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

两个视图中的每个视图都有其自己的BindingContext。包含ListView的视图具有类型为BasketEquipamentPartViewModel的BindingContext,这就是{Binding ItensOrder}为ItemsSource选择正确的集合的原因。

然后Xamarin将多次使用BasketEquipamentPartCell,对于集合的每个元素一次,将BindingContext设置为每个OrderItem。因此,BasketEquipamentPartCell没有任何直接引用集合的BindingContext的方法。在按钮上评估Command="{Binding BindingContext.removeItemOder}"时,Xamarin.Forms将通过OrderItem的属性查找removeItemOder,但找不到它。当Xamarin.Forms找不到属性时,它会默默地忽略它,因此您的应用程序的其余部分都可以正常工作。

要解决此问题,您需要在OrderItem上定义一个可以绑定的Command属性。

实施方法草图

一种解决方法是在BasketEquipamentPartViewModel上添加一个方法,该方法使用MessagingCenter(用于其他用途)来侦听删除项的请求:

public void CreateMessaging()
{
    MessagingCenter.Subscribe<OrderItem>(this, "RemoveOrderItem", RemoveItem);
    // the rest of CreateMessaging you already have
}

private void RemoveItem(OrderItem itemToRemove)
{
    // do the stuff you're already doing in removeItemOder
}

请注意,您似乎没有在removeItemOder中进行任何异步工作,因此您应该删除异步并使其返回void。

然后在OrderItem类中,创建如下命令:

private ICommand _removeItemOrder;
public ICommand removeItemOder => _removeItemOrder ??
       (_removeItemOrder = new Command<OrderItem>(item => MessagingCenter.Send(this, "RemoveOrderItem"));

然后,{Binding BindingContext.removeItemOder}(或在这里只是{Binding removeItemOder}-BindingContext是多余的)将成功找到要调用的命令。