I'm a newbie so excuse my question if it's too fade or if it's unclear.
any way, In my UI (WPF), i have a ListView that i created containing an observable collection of Type Collection = new ObservableCollection<type>
and i have two Buttons "Add" & "Delete" I want to do this:
1-Whenever i select an item from my ListView in the UI(just click on it) , and click the "Add" button, the item is stored in a List called Scenario (Scenario = new List<type>
).
2- Whenever i click the "Delete" button the Scenario list becomes empty.
I've tried something out but it doesn't work like it should, i can only add one item to the list Scenario and then it is blocked (when debugging) in
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
Can someone tell me why? and how to fix it? As for the "Delete" Button i didn't get to it yet because the other one doesn't work properly.
if you can propose a new solution or a solution for this problem i would be so thankful.
This is what i've done so far.
This is the code in the MainWindowModel :
private ObservableCollection<Type> _collection,_scenario;
public MainWindowModel()
{
Collection = new ObservableCollection<type>();
Scenario=new ObservableCollection<Type>();
DeleteCommand = new RelayCommand(o => DeleteExecute());
AddTypeCommand = new RelayCommand(o => AddTypeExecute());
}
private Type _isSelected;
public Type IsSelected;
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_isSelected = value;
RaisePropertyChanged(nameof(IsSelected));
}
}
}
public ICommand DeleteCommand
{
get;
private set;
}
private RelayCommand _addTypeCommand;
public ICommand AddTypeCommand
{
get
{
if (_addTypeCommand == null)
{
_addTypeCommand = new RelayCommand(o => AddTypeExecute());
}
return _addTypeCommand;
}
set { }
}
private void DeleteExecute()
{
Scenario.Clear(); // Would this Work ?
}
private bool CanExecuteAddTypeCommand()
{
return true;
}
private void AddTypeExecute()
{
if (IsSelected != null)
{
Scenario.Add(IsSelected);
}
}
public ObservableCollection<Type> collection
{
get { return _collection; }
set { SetPropertyAndFireEvent(ref _collection, value); }
}
public ObservableCollection<Type> Scenario
{
get { return _scenario; }
set { SetPropertyAndFireEvent(ref _scenario, value); }
}
as for the MainWindowModel
<Window.DataContext>
<viewModels:MainWindowModel />
</Window.DataContext>
<Grid>
<ListView Grid.Row="2"
Grid.Column="0"
ItemsSource="{Binding Collection}"
SelectedItem="{Binding IsSelected}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Command="{Binding AddTypeCommand}"
Width="100"
Height="100"
Content="Add"
Grid.Row="0"
Grid.Column="2"/>
<Button Command="{Binding DeleteCommand}"
Content="Delete"
Width="100"
Height="100"
Grid.Row="2"
Grid.Column="2" />
</Grid>
As for the RelayCommand.cs
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
//Notifies the Button bounded to the ICommand that the value returned by CanExecute has changed
public event EventHandler CanExecuteChanged
{
//raised whenever the commandmanager thinks that something has changed that will affect the ability of commands to execute
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
Try passing selectedItem as parameter for command,you dont pass anything and try to add... name your ListView:
<ListView x:Name="listView"
and pass selectedItem as commandParameter
<Button Command="{Binding AddTypeCommand}"
CommandParameter="{Binding ElementName=listView, Path=SelectedItem}"
Width="100"
Height="100"
Content="Add"
Grid.Row="0"
Grid.Column="2" />
and then do your logic for adding, now you have parameter to add to your list.
EDIT: Here is some code that works, as i have understand that u need something like this.
ViewModel _> where all collection and command are created:
public class TestVM : INotifyPropertyChanged
{
public TestVM()
{
ListOne = new ObservableCollection<string>()
{
"str1","str2","str3"
};
// command
AddTypeCommand = new RelayCommand(OnAddExecute);
DeleteTypeCommand = new RelayCommand(OnDeleteExecuted);
}
private void OnDeleteExecuted()
{
ListTwo.Clear();
}
private void OnAddExecute()
{
if (SelectedItem != null)
{
ListTwo.Add(SelectedItem);
}
}
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
OnPropertyChanged();
}
}
}
private ObservableCollection<string> _listOne;
public ObservableCollection<string> ListOne
{
get
{
return _listOne;
}
set
{
if (_listOne != value)
{
_listOne = value;
OnPropertyChanged();
}
}
}
public ObservableCollection<string> ListTwo { get; set; } = new ObservableCollection<string>();
public RelayCommand AddTypeCommand { get; private set; }
public RelayCommand DeleteTypeCommand { get; private set; }
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
RellayCommand how i implement it:
public class RelayCommand : ICommand
{
private Action _executeMethod;
private Func<bool> _canExecuteMethod;
#region RelayCommand ctor
public RelayCommand(Action executeMethod)
{
_executeMethod = executeMethod;
}
public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod)
{
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
#endregion
public void RaiseCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
#region ICommand Members
bool ICommand.CanExecute(object parameter)
{
if (_canExecuteMethod != null)
return _canExecuteMethod();
if (_executeMethod != null)
return true;
return false;
}
void ICommand.Execute(object parameter)
{
if (_executeMethod != null)
_executeMethod();
}
public event EventHandler CanExecuteChanged = delegate { };
#endregion
}
//--------------------------------------------------------------------------------------------
public class RelayCommand<T> : ICommand
{
private Action<T> _executeMethod;
private Func<T, bool> _canExecuteMethod;
#region RelayCommand ctor
public RelayCommand(Action<T> executeMethod)
{
_executeMethod = executeMethod;
}
public RelayCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
{
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
#endregion
public void RaiseCanExecuteChanged()
{
CanExecuteChanged(this, EventArgs.Empty);
}
#region ICommand Members
bool ICommand.CanExecute(object parameter)
{
var Tparam = (T)parameter;
if (_canExecuteMethod != null)
return _canExecuteMethod(Tparam);
if (_executeMethod != null)
return true;
return false;
}
void ICommand.Execute(object parameter)
{
if (_executeMethod != null)
_executeMethod((T)parameter);
}
public event EventHandler CanExecuteChanged = delegate { };
#endregion
}
And MainWindow.xaml just to show purpose. Selecting on one item in 1rst list and pressing button Add will add it to second ListView. DeleteButton will clear second list.
<Window x:Class="WpfApp5.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:WpfApp5"
mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525">
<Window.DataContext>
<local:TestVM />
</Window.DataContext>
<Grid>
<ListView x:Name="listViewOne"
ItemsSource="{Binding ListOne}"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}"
Width="100"
Height="200"
Margin="17,17,400,105" />
<ListView x:Name="listViewTwo"
ItemsSource="{Binding ListTwo}"
Width="100"
Height="200"
Margin="339,17,78,105" />
<Button Command="{Binding AddTypeCommand}"
Content="Add"
Grid.Row="0"
Margin="208,111,198,178" />
<Button Command="{Binding DeleteTypeCommand}"
Content="Delete"
Grid.Row="0"
Margin="208,157,198,132" />
</Grid>
</Window>