-1

I have a db column userstatus where default is true. Now I have a checkbox which allows the user to checked on it to disable the user. But now even I checked on the checkbox the user status is still showing true in the database. How can I fix this issue.

Here is the View:

<CheckBox x:Name="cbUserStatus" Content="Disable" IsChecked="{Binding UserStatus}"/>

Here is the code behind the View:

int userStatus = Convert.ToInt32(cbUserStatus.IsChecked.Value);



try
        {
            string query = "Update users set USER_FIRSTNAME = '" + firstName + "', USER_ROLE = '"+ userRole + "', USER_STATUS = '"+ userStatus +"' where ID = " + id;

            db.QueryCommand(query);

            MessageBox.Show("User updated successfully");
            this.Close();
            admin_home adminWindow = new admin_home();
            adminWindow.Show();

        }
        catch (MySqlException ex)
        {
            MessageBox.Show(ex.ToString());
        }

Here is my user Model:

 private bool userstatus;


    public bool UserStatus
    {
        get { return (userstatus == false) ? true : false; }
        set
        {
            userstatus = value;
            OnPropertyChanged("UserStatus");
        }
    }
  • when did you set your data context? In your code behind, you should set the DataContext: this.DataContext = new YourModel() for an example – Nhan Phan Sep 07 '18 at 04:59
  • 1
    Unrelated tip: avoid string concatenation to create a query: your code is vulnerable to SQL injection attacks: use SQL parameters instead. – Richardissimo Sep 07 '18 at 05:17

3 Answers3

1

Don't do a mess of conversion, view and viewmodel. Leave model as it is in a database. If the status is int in database leave it as int. Do inversion via converter. Write to your db using data from viewmodel.

Make inverse boolean converter:

public class InverseBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            bool testValue = System.Convert.ToBoolean(value);
            return !testValue; // or do whatever you need with this boolean
        }
        catch { return true; } // or false
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            int testValue = System.Convert.ToInt32(!((bool)value));
            return testValue; // or do whatever you need with this boolean
        }
        catch { return 1; } 
    }
}

Specify converter:

<Window.Resources>
        <yourNS:InverseBooleanConverter x:Key="inverseIntBoolConverter"/>
...

<CheckBox x:Name="cbUserStatus" Content="Disable" IsChecked="{Binding UserStatus,Converter={StaticResource inverseIntBoolConverter}}"/>

ViewModel:

public int UserStatus
    {
        get { return userstatus; }
        set
        {
            if (value!=userstatus)
            {
               userstatus = value;
               OnPropertyChanged(nameof(UserStatus)); 
            } 
        }
    }

Write to your db from viewModel:

int userStatus = viewModel.UserStatus;

Use parameters when constructing query to prevent SQL injections:

var comm = connection.CreateCommand();
comm.CommandText = "Update users set USER_FIRSTNAME = @firstName , USER_ROLE = @userRole, USER_STATUS = @userStatus where ID = @id;"
comm.Parameters.Add("@firstName",firstName );
comm.Parameters.Add("@userRole", userRole);
comm.Parameters.Add("@userStatus", userStatus);
comm.Parameters.Add("@id", id);
comm.ExecuteNonQuery();

Converter Code for bool Status in ViewModel

    public class InverseBooleanConverter : IValueConverter
    {
      public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
      {
         return !((bool)value);                
      }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
       return Convert(value, targetType, parameter, culture);
    }
 }
Access Denied
  • 7,145
  • 4
  • 29
  • 62
  • Default Binding mode of IsChecked os CheckBox is TwoWay: https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-binding-overview. I think he have other problem. – Nhan Phan Sep 07 '18 at 04:59
  • 1
    @NhanPhan thanks, you are quite right on that. I always specify TwoWay, didn't know that. – Access Denied Sep 07 '18 at 05:30
  • @AccessDenied by default my user_status column in the database is boolean which accepts either 1 or 0. and I am really getting you want me to create a new UserStatus method in the viewmodel? I already have the UserStatus method in my model. Should i create another one? Please advice on this. – anonymous_apple Sep 07 '18 at 07:13
  • @AccessDenied the InverseBooleanConverter is not working. Its showing **Convert.ToBoolean is not valid in the current context** – anonymous_apple Sep 07 '18 at 07:47
  • @AccessDenied although i have found the solution but I am interested in your solution actually. Can you please elaborate for me your solution because its not working on my side.... If can pls share me the code so that i can have a better understanding.. – anonymous_apple Sep 07 '18 at 08:04
  • @anonymous_apple it should be System.Convert, I've updated my answer. It conflicts with converter methods and you should specify namespace for it. – Access Denied Sep 07 '18 at 08:11
  • @AccessDenied can you please share me a sample code on it? This is my first time I am implementing the IValueConverter and how about the ViewModel? should i create the userstatus method again in the view model? – anonymous_apple Sep 07 '18 at 08:22
  • @anonymous_apple it's already in my answer, take a look at it. – Access Denied Sep 07 '18 at 08:23
  • @AccessDenied in my model the userstatus is boolean – anonymous_apple Sep 07 '18 at 08:26
  • @anonymous_apple I added another converter to the end of my answer – Access Denied Sep 07 '18 at 08:30
  • @AccessDenied I dont understand this part **int userStatus = viewModel.UserStatus;** where should this code included in? is it in the views or view model? – anonymous_apple Sep 07 '18 at 09:31
  • @anonymous_apple you should access db from ViewModel (VM). Ideally via commands. https://stackoverflow.com/a/24847186/1099716 I don't know how you set your datacontext. If you set it from codebehind you can access VM. Also you can get viewmodel from codebehind like this https://stackoverflow.com/a/24849106/1099716 – Access Denied Sep 07 '18 at 09:38
0

I guess you are missing inverse clause in your code-behind. As you are not using UserStatus of ViewModel, you should update your code as

int userStatus = if( Convert.ToInt32(cbUserStatus.IsChecked.Value) == 0) ? 1 : 0 ;

Instead of

int userStatus = Convert.ToInt32(cbUserStatus.IsChecked.Value);
Dishant
  • 1,425
  • 11
  • 19
0

I think your problem is because of logic coding: you always get value by !userstatus Let see your current UserStatus code:

private bool userstatus;


public bool UserStatus
{
    get { return (userstatus == false) ? true : false; }
    set
    {
        userstatus = value;
        OnPropertyChanged("UserStatus");
    }
}

If the check box is true, and user click on the checkbox, then value of userstatus is set to false by your set function. And the check box get its Value via UserStatus property: "return (userstatus == false) ? true : false;" will be true value. And it will be always true.

=> Solution is change your UserStatus logic:

    private bool userstatus;


    public bool UserStatus
    {
        get { 
               return userstatus;
        }

        set
        {
            userstatus = value;
            OnPropertyChanged("UserStatus");
        }
    }
Nhan Phan
  • 1,212
  • 1
  • 10
  • 28