0

I have problem with ICommand interface. My button doesn't work properly. I want to enable it when name and id are filled. It seems that name and id not have a value. At least I think that. I have tried create new object of MainWindow and refer to field text but it didnt't work

XAML

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:m="clr-namespace:WpfApplication1"
    xmlns:mv="clr-namespace:WpfApplication1"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <m:Repository x:Key="P"/>
    <mv:ViewM x:Key="C"/>
</Window.Resources>

<Border CornerRadius="23" Background="Black" Padding="10">
    <StackPanel DataContext="{Binding Source={StaticResource C}}">

        <TextBlock Foreground="White" HorizontalAlignment="Center" Text="Main" Padding="0,5,0,0"/>
        <Separator Margin="0,10,0,0"/>
        <TextBox HorizontalAlignment="Center" Height="30" Width="200" IsReadOnly="False" Text="{Binding ID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextAlignment="Center" Padding="0,5,0,0" Margin="0,4,0,0" MaxLength="20"/>
        <TextBox HorizontalAlignment="Center" Height="30" Width="200" IsReadOnly="False" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextAlignment="Center" Padding="0,5,0,0" Margin="0,4,0,0" MaxLength="20"/>
        <TextBox HorizontalAlignment="Center" Height="30" Width="200" IsReadOnly="True" Text="{Binding Full, UpdateSourceTrigger=PropertyChanged}" TextAlignment="Center" Padding="0,5,0,0" Margin="0,4,0,0" MaxLength="20"/>
        <Button  HorizontalAlignment="Center" Height="20" Width="100" Content="CHuj" Margin="0,20,0,0"
                 Command="{Binding com}" CommandParameter="{Binding Repo, UpdateSourceTrigger=PropertyChanged}"
        </Button>
    </StackPanel>

</Border>

ICommand

public class Icom : ICommand
{

    public ViewM VieM { get; set; }

    public event EventHandler CanExecuteChanged;


    public Icom(ViewM view)
    {
        this.VieM = view;
    }

    public bool CanExecute(object parameter)
    {
        Repository R = (Repository)parameter;
        if (R != null)
        {
            if (string.IsNullOrEmpty(R.Name) || (string.IsNullOrEmpty(R.ID)))
                return false;

            return true;
        }

       return false;
    }

    public void Execute(object parameter)
    {
        VieM.Wy();
    }
}

Repository

public class Repository : INotifyPropertyChanged
{

    private string _id;

    public string ID
    {
        get { return _id; }
        set { _id = value;
            OnPropertyChanged("ID");
            OnPropertyChanged("Full");
        }

    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set { _name = value;
            OnPropertyChanged("Name");
            OnPropertyChanged("Full");
        }

    }

    private string _full;

    public string Full
    {
        get { return Name + " " + ID; }
        set { _full = value;
            OnPropertyChanged("Full");
        }

    }

    public Repository()
    {
        this.Name = "";
        this.ID = "";
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

ViewModel

 public class ViewM : INotifyPropertyChanged
{

    private string _id;

    public string ID
    {
        get { return _id; }
        set
        {
            _id = value;
            Repo = new Repository()
            {
                Full = this.Full,
                Name = this.Name,
                ID = this.ID
            };
            OnPropertyChanged("ID");
            OnPropertyChanged("Full");
        }

    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            Repo = new Repository()
            {
                Full = this.Full,
                Name = this.Name,
                ID = this.ID
            };
            OnPropertyChanged("Name");
            OnPropertyChanged("Full");
        }

    }

    private string _full;

    public string Full
    {
        get { return Name + " " + ID; }
        set
        {
            _full = value;
            Repo = new Repository()
            {
                Full = this.Full,
                Name = this.Name,
                ID = this.ID                 
            };
            OnPropertyChanged("Full");
        }

    }

    private Repository _repo;

    public Repository Repo
    {
        get { return _repo; }
        set
        {
            _repo = value;
            OnPropertyChanged("Repo");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public Icom com { get; set; }

    public ViewM()
    {
        this.com = new Icom(this);
    }

    public void Wy()
    {
        MessageBox.Show("Text");
    }
}
J.J
  • 111
  • 1
  • 13
  • [To ensure that your events are being raised properly you should raise the CanExecuteChanged event when the \[...\] value changes.](https://stackoverflow.com/a/12371891/7598462) – kowsky Mar 06 '18 at 15:53
  • Possible duplicate of [How do I pass a variable as a CommandParameter](https://stackoverflow.com/questions/12371253/how-do-i-pass-a-variable-as-a-commandparameter) – kowsky Mar 06 '18 at 15:53

2 Answers2

1

Your button needs to reevaluate whether or not it can be executed after your values change.

The CommandManager only pays attention to certain conditions in determining when the command target has changed, such as change in keyboard focus. In situations where the CommandManager does not sufficiently determine a change in conditions that cause a command to not be able to execute, the CommandManager.InvalidateRequerySuggested Method can be called to force the CommandManager to raise the RequerySuggested event.

Frinavale
  • 3,908
  • 10
  • 44
  • 74
0

I got it

public class Icom : ICommand
{

    public ViewM VieM { get; set; }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

    public Icom(ViewM view)
    {
        this.VieM = view;
    }

    public bool CanExecute(object parameter)
    {
        Repository R = (Repository)parameter;
        if (R != null)
        {
            if (string.IsNullOrEmpty(R.ID) || (string.IsNullOrEmpty(R.Name)))
                return false;

            return true;
        }
        return false;
    }

    public void Execute(object parameter)
    {
        VieM.Wy();
    }
}

And in ViewM

 private Repository _repo;

    public Repository Repo
    {
        get { return _repo; }
        set
        {
            _repo = value;
            OnPropertyChanged("Repo");
            com.RaiseCanExecuteChanged();
        }
    }
J.J
  • 111
  • 1
  • 13