Click here to Skip to main content
15,042,397 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello!

I have a button which delete rows off of my DataGrid, whenever I have a row selected.
I use a RelayCommand to accomplish that.
But my button refuses to enable like I want it to!

slette — ImgBB[^]

I believe I've understood it to be an issue with the CanExecute functionality of RelayCommand.

How can I modify it to enable it upon row selection?

What I have tried:

C#
private bool RemoveLicenseHolderCanExecute(LicenseHolder myLicenseHolder) {

    return LicenseHolders.Contains(myLicenseHolder);
}


In the code-behind, I've set IsEnabled = true; under the SelectionChanged-event.
And in the XAML, I've set the button property like so: IsEnabled="False"

If I remove the command bindings from the button, the button enables upon row-selection as expected.

The entirety of my RelayCommand is as follows (it's in my ViewModel):

C#
private static bool RemoveFromDB(LicenseHolder myLicenseHolder) {

    string sqlString = $"Delete from tblLicenseHolder where ID = '{myLicenseHolder.ID}'";

    if (MessageBox.Show("Er du sikker på at du ønsker å slette valgt løyvehaver?", "Slett løyvehaver", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) {

        try {

            using (SqlConnection sqlCon = new(ConnectionString.connectionString))
            using (SqlCommand sqlCmd = new(sqlString, sqlCon)) {

                sqlCon.Open();
                sqlCmd.ExecuteNonQuery();
                return true;
            }

        }
        catch {

            return false;
        }

    } else {

        return false;
    }
}

private void RemoveLicenseHolderExecute(LicenseHolder myLicenseHolder) {

    bool result = RemoveFromDB(myLicenseHolder);
    if (result)
        LicenseHolders.Remove(myLicenseHolder);
}

private RelayCommand<LicenseHolder> _removeLicenseHoldersCommand;

public RelayCommand<LicenseHolder> RemoveLicenseHoldersCommand => _removeLicenseHoldersCommand
    ??= new RelayCommand<LicenseHolder>(RemoveLicenseHolderExecute, RemoveLicenseHolderCanExecute);

private bool RemoveLicenseHolderCanExecute(LicenseHolder myLicenseHolder) {

    return LicenseHolders.Contains(myLicenseHolder);
}
Posted
Updated 6-Jul-21 23:11pm
v4
Comments
Chris Copeland 6-Jul-21 10:14am
   
How are you passing the LicenseHolder into the command? Are you using binding to correctly pass it in as the command parameter? Can we see the XAML for the button part of the screen?
Flidrip 6-Jul-21 10:38am
   
Hi @Chris Copeland! Thanks for taking the time to comment.

This is the XAML for my 'Delete button':


<button
x:name="btnDelete"
command="{Binding RemoveLicenseHoldersCommand}" commandparameter="{Binding
SelectedItem, ElementName=dgLicenseHolder}" isenabled="False" style=" {DynamicResource RoundedButtonStyle}">
Richard Deeming 6-Jul-21 11:37am
   
Why are you setting IsEnabled="False" on the button, rather than letting the command decide whether or not it's enabled?
Flidrip 6-Jul-21 15:55pm
   
I commented out the private bool RemoveLicenseHolderCanExecute(LicenseHolder myLicenseHolder, and kept the IsEnabled=false in the XAML, and now the function works as I want it to.
I will do some research on what the part I removed actually does, because I can't see that I need it. Would you recommend against removing it? I don't understand what it does in order to disable the button... Because when I tried removing the IsEnabled=false in the XAML, the button would still be disabled.
Richard Deeming 6-Jul-21 11:36am
   
string sqlString = $"Delete from tblLicenseHolder where ID = '{myLicenseHolder.ID}'";

Your code is vulnerable to SQL Injection[^]. NEVER use string concatenation / interpolation to build a SQL query. ALWAYS use a parameterized query.

Everything you wanted to know about SQL injection (but were afraid to ask) | Troy Hunt[^]
How can I explain SQL injection without technical jargon? | Information Security Stack Exchange[^]
Query Parameterization Cheat Sheet | OWASP[^]

1 solution

I don't believe that updates to a CommandParameter actually cause the command to refresh the CanExecute state. I couldn't find any examples where this was the case, so you might need to think about building that logic into the view-model.

For example, create a binding between your dgLicenseHolder.SelectedItem and a view-model property, and then when that property is changed you can force the command to refresh itself. With RelayCommand I believe there's a method named RaiseCanExecuteChanged() which can do that.
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900