Muhammad Touseef
Muhammad Touseef

Reputation: 4465

uwp gridview delete item with button within datatemplate

I have a gridview in UWP app and I have put a button in each gridview item in datatemplate so that it can be used to delete/remove that specific item from the gridview ( removing it from observableCollection behind). I am not using MVVM approach, because I am not much familiar with it, I am using a normal Observable Collection for binding of data and data template.

if you can suggest me a better way to do it, myabe using MVVM please suggest me how to do it. Thanks in advance

Code :

XAML GRID VIEW (button with the red back ground is the button I wanna use to delete item)

<controls:AdaptiveGridView Name="HistoryGridView" StretchContentForSingleRow="False"
                           Style="{StaticResource MainGridView}"
                           ItemClick ="HistoryGridView_SelectionChanged"
                           ItemsSource="{x:Bind HistoryVideos, Mode=OneWay}">
    <controls:AdaptiveGridView.ItemTemplate>
        <DataTemplate  x:DataType="data:Video">
            <StackPanel Margin="4" >
                <Grid>
                    <Button  Background="Red"
                            HorizontalAlignment="Right" VerticalAlignment="Top"
                            Height="36" Canvas.ZIndex="1"
                            Style="{StaticResource TransparentButton}" Width="36">
                        <fa:FontAwesome Icon="Close" FontSize="20" HorizontalAlignment="Center" Foreground="White"
                                            />
                    </Button>
                    <Image  Canvas.ZIndex="0"    Source="{x:Bind Thumbnail}" Style="{StaticResource GridViewImage}"/>
                    <Border Style="{StaticResource TimeBorder}" Height="Auto" VerticalAlignment="Bottom"
                            Canvas.ZIndex="1"
                            HorizontalAlignment="Left">
                        <TextBlock Text="{x:Bind Duration}" Foreground="White" Height="Auto"/>
                    </Border>
                </Grid>
                <TextBlock Text="{x:Bind Name}"  Style="{StaticResource GridViewVideoName}"/>
                <TextBlock Text="{x:Bind ParentName}"  Style="{StaticResource GridViewParentName}"/>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
                    <TextBlock Text="{x:Bind Views}" Style="{StaticResource GridViewViews}"/>
                    <TextBlock Text="Views" HorizontalAlignment="Right"/>
                </StackPanel>
            </StackPanel>

        </DataTemplate>
    </controls:AdaptiveGridView.ItemTemplate>
</controls:AdaptiveGridView>

Code Behind

public History()
{
    this.InitializeComponent();
    HistoryVideos = new ObservableCollection<Video>();
}

public ObservableCollection<Video> HistoryVideos { get; private set; }

I am using onnavigated to method for filling the collection and it works fine and also I guess that is not relevent here.

Upvotes: 2

Views: 2001

Answers (1)

Jayden
Jayden

Reputation: 3286

We can add the Command to the Button to invoke when this button is pressed and we can use parameter to pass to the Command property.

To use the Command, we should be able to define a DelegateCommand class that inherits from the ICommand.

For example:

internal class DelegateCommand : ICommand
{
    private Action<object> execute;
    private Func<object, bool> canExecute;

    public DelegateCommand(Action<object> execute)
    {
        this.execute = execute;
        this.canExecute = (x) => { return true; };
    }

    public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged;

    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }
    }

    public void Execute(object parameter)
    {
        execute(parameter);
    }
}

We can add the Id property in the Video, then we can pass the Id property to the CommandParameter. When we click the Button, the ExecuteDeleteCommand method will be fired. We can use the Id to find the Video in the HistoryVideos and use the Remove method to remove it.

The ViewModel code:

internal class ViewModel
{
    private ObservableCollection<Viedo> _videos;

    public ObservableCollection<Viedo> Videos
    {
        get
        {
            return _videos;
        }
        set
        {
            if (_videos != value)
            {
                _videos = value;
            }
        }
    }

    public ICommand DeleteCommand { set; get; }

    private void ExecuteDeleteCommand(object param)
    {
        int id = (Int32)param;
        Viedo cus = GetCustomerById(id);

        if (cus != null)
        {
            Videos.Remove(cus);
        }
    }

    private Viedo GetCustomerById(int id)
    {
        try
        {
            return Videos.First(x => x.Id == id);
        }
        catch
        {
            return null;
        }
    }

    public ViewModel()
    {
        Videos = new ObservableCollection<Viedo>();
        for (int i = 0; i < 5; i++)
        {
            Videos.Add(new Viedo());
            Videos[i].Name = "Name";
            Videos[i].Id = i;
        }

        this.DeleteCommand = new DelegateCommand(ExecuteDeleteCommand);
    }
}

The XAML code:

<GridView Name="MyGridView"  ItemsSource="{Binding Videos}">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Name}"></TextBlock>
                <Button  Background="Red"
                    HorizontalAlignment="Right" VerticalAlignment="Top"
                    Height="36" Canvas.ZIndex="1"
                Width="36"  Command="{Binding DataContext.DeleteCommand, ElementName=MyGridView}" CommandParameter="{Binding Id}">
                </Button>
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

The code behind:

private ViewModel myViewModel;

public MainPage()
{
    this.InitializeComponent();
    myViewModel = new ViewModel();
    MyGridView.DataContext = myViewModel;
}

Update:

<GridView Name="MyGridView"  ItemsSource="{x:Bind myViewModel.Videos}">
    <GridView.ItemTemplate>
        <DataTemplate x:DataType="local:Viedo">
            <StackPanel>
                <TextBlock Text="{x:Bind Name}"></TextBlock>
                <Button  Background="Red"
                    HorizontalAlignment="Right" VerticalAlignment="Top"
                    Height="36" Canvas.ZIndex="1"
                Width="36"  Command="{Binding DataContext.DeleteCommand, ElementName=MyGridView}" CommandParameter="{Binding Id}">
                </Button>
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

Upvotes: 2

Related Questions