WPF MVVM Добавить новый объект в ObservableCollection с помощью текстовых полей и ICommand
Новое в мире WPF и шаблон MVVM. Я надеялся, что кто-нибудь сможет предоставить очень простое описание того, как я могу создать и добавить новый объект в observableColllection, используя текстовые поля для установки свойств и команду, запускаемую кнопкой.
Что у меня так далеко:
модель
public class CarModel : NotifyBase
{
#region Private Members
/// <summary>
/// Private members for the class Car
/// </summary>
private string _manufacturer;
private string _model;
private string _year;
private string _color;
private string _regNumber;
private EngineModel _eng;
#endregion
#region Public Properties
/// <summary>
/// Public properties for the class Car (used for view binding)
/// </summary>
public string Manufacturer {
get { return _manufacturer; }
set {
if (_manufacturer != value)
{
_manufacturer = value;
RaisePropertyChanged("Manufacturer");
}
}
}
public string Model {
get { return _model; }
set {
if (_model != value)
{
_model = value;
RaisePropertyChanged("Model");
}
}
}
.
.
.
ViewModel
class MainViewModel : NotifyBase
{
#region Private Members
/// <summary>
/// Privtae members for the class MainViewModel
/// </summary>
private ObservableCollection<CarModel> _carRegistry;
private CarModel _selectedCar;
private CarModel _car;
private ICommand _addCarCommand;
#endregion
#region Public Properties
/// <summary>
/// Public members for the class MainModelView (used for view binding)
/// </summary>
public ObservableCollection<CarModel> CarRegistry{
get { return _carRegistry; }
set {
_carRegistry = value;
RaisePropertyChanged("CarRegistry");
}
}
public CarModel SelectedCar
{
get { return _selectedCar; }
set
{
_selectedCar = value;
RaisePropertyChanged("SelectedCar");
}
}
public CarModel Car
{
get { return _car; }
set {
_car = value;
RaisePropertyChanged("Car");
}
}
public ICommand AddCarCommand
{
get {
if (_addCarCommand == null)
{
_addCarCommand = new RelayCommand(param =>new CarModel(), param => true);
}
return _addCarCommand;
}
}
#endregion
#region Constructor
/// <summary>
/// MainViewModel constructor
/// </summary>
public MainViewModel()
{
CarRegistry = new ObservableCollection<CarModel>()
{
//Dummy data
new CarModel(){Manufacturer = "Volvo", Model = "V70", Year = "2000", Color = "White", RegNumber = "CDC-123",
Engine = new EngineModel(){Serial = "END125456#", Volume = "2.0"}},
new CarModel(){Manufacturer = "Volvo", Model = "V40", Year = "2005", Color = "Black", RegNumber = "ITI-456",
Engine = new EngineModel(){Serial = "IND554567#", Volume = "1.6"}},
new CarModel(){Manufacturer = "Ford", Model = "Escort", Year = "1995", Color = "Blue", RegNumber = "GHD-777",
Engine = new EngineModel(){Serial = "GHTSJ5556#", Volume = "2.0"}},
};
}
#endregion
#region Methods
private void AddCar(object o)
{
//add new carModel to _carRegistry
}
#endregion
}
RelayCommand
class RelayCommand:ICommand
{
#region Private Members
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
//if(parameter != null)
_canExecute(parameter);
}
}
Если я правильно понимаю, мне нужно привязать текстовые поля к свойствам в ViewModel и кнопку для запуска AddCarCommand
но мне неясно, как это должно быть реализовано. Любая помощь будет принята с благодарностью!!!
//Натан
редактировать
XAML
В настоящее время мой xaml выглядит так:
<Window x:Class="CarData_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CarData_Test"
Title="Car Data Test" Height="606.645" Width="758.759">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="CAR INFORMATION" VerticalAlignment="Top" FontWeight="Bold" FontFamily="Segoe WP Light" RenderTransformOrigin="0.497,-1.834" FontSize="16"/>
<TextBlock HorizontalAlignment="Left" Margin="28,10,0,0" TextWrapping="Wrap" Text="CAR REGISTER" VerticalAlignment="Top" FontFamily="Segoe WP Light" FontSize="16"/>
<ListView HorizontalAlignment="Left" Height="446" Margin="28,31,0,0" VerticalAlignment="Top" Width="323" ItemsSource="{Binding CarRegistry}" SelectedItem="{Binding SelectedCar}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="Reg Number" DisplayMemberBinding="{Binding RegNumber}"/>
<GridViewColumn Width="Auto" Header="Manufacturer" DisplayMemberBinding="{Binding Manufacturer}"/>
<GridViewColumn Width="Auto" Header="Model" DisplayMemberBinding="{Binding Model}"/>
<GridViewColumn Width="Auto" Header="Year" DisplayMemberBinding="{Binding Year}"/>
<GridViewColumn Width="Auto" Header="Color" DisplayMemberBinding="{Binding Color}"/>
</GridView>
</ListView.View>
</ListView>
<StackPanel Grid.Column="1" HorizontalAlignment="Left" Height="446" Margin="10,31,0,0" VerticalAlignment="Top" Width="335">
<TabControl DataContext="{Binding SelectedCar}" Height="446">
<TabItem Header="Overview">
<Grid Background="#FFE5E5E5">
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="20 30 0 0" Content="Registration Number"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Name="txtbox_regNumber" Text="{Binding RegNumber, UpdateSourceTrigger=PropertyChanged}" Width="112" Margin="25 3 0 0"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Manufacturer" Margin="21 0 0 0"/>
<Label Content="Model" Margin="76 0 0 0"></Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Name="txtbox_manufacturer" Text="{Binding Manufacturer, UpdateSourceTrigger=PropertyChanged}" Width="112" Margin="25 0 0 0"/>
<TextBox Name="txtbox_model" Text="{Binding Model, UpdateSourceTrigger=PropertyChanged}" Width="112" Margin="44 0 0 0"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Year" Margin="22 0 0 0"/>
<Label Content="Color" Margin="123 0 0 0"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Name="txtbox_year" Text="{Binding Year, UpdateSourceTrigger=PropertyChanged}" Width="112" Margin="25 0 0 0"/>
<TextBox Name="txtbox_color" Text="{Binding Color, UpdateSourceTrigger=PropertyChanged}" Width="112" Margin="44 0 0 0"/>
</StackPanel>
</StackPanel>
<GroupBox Header="Edit" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="182" Width="291"/>
</Grid>
</TabItem>
<TabItem Header="Engine Data">
<Grid Background="#FFE5E5E5">
<StackPanel>
<StackPanel>
<Label Content="Serial Number" Margin="20 30 0 0"/>
</StackPanel>
<StackPanel>
<TextBox HorizontalAlignment="Left" Text="{Binding Engine.Serial, UpdateSourceTrigger=PropertyChanged}" Width="112" Margin="25 3 0 0"/>
</StackPanel>
<StackPanel>
<Label Content="Volume" Margin="20 15 0 0"/>
</StackPanel>
<StackPanel>
<TextBox HorizontalAlignment="Left" Text="{Binding Engine.Volume, UpdateSourceTrigger=PropertyChanged}" Width="112" Margin="25,0,0,0"/>
</StackPanel>
</StackPanel>
<GroupBox Header="Edit" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="182" Width="291"/>
</Grid>
</TabItem>
</TabControl>
</StackPanel>
<Button Command="{Binding AddCarCommand}" Content="Add" Grid.Column="1" HorizontalAlignment="Left" Margin="10,494,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
В идеале я хотел бы иметь возможность добавлять через текстовые поля, которые находятся на вкладке, но в настоящее время они привязаны к selectedCar.
2 ответа
Ваш RelayCommand
должен позвонить вашему AddCar
метод:
public ICommand AddCarCommand
{
get
{
if (_addCarCommand == null)
{
_addCarCommand = new RelayCommand(param => AddCar(param), param => true);
}
return _addCarCommand;
}
}
В этом методе вы добавляете новый Car
объект к исходной коллекции:
private void AddCar(object o)
{
CarRegistry.Add(new CarModel { Model = Car.Model });
}
По мнению, вы можете связать TextBoxes
к свойствам объекта Car:
<TextBox Text="{Binding Car.Model, UpdateSourceTrigger=PropertyChanged}" />
... и Button
к свойству команды:
<Button Command="{Binding AddCarCommand}" />
Не забудьте установить DataContext
зрения:
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
... и на самом деле создать Car
Объект где-то в представлении модели:
private CarModel _car = new CarModel();
Редактировать:
Execute
метод вашей команды должен вызывать _execute
действие:
public void Execute(object parameter)
{
_execute(parameter);
}
На ваш взгляд, в основном XAML, вам нужно привязать команду к кнопке. Кнопка имеет свойство команды. Привязать к нему команду, например,
<Button Command={Binding AddCarCommand} CommandParameter="{Binding SelectedCar}">
Для всей этой работы вы должны установить свойство DataContext view в MainViewModel