WPF MVVM使用文本框和ICommand将新对象添加到ObservableCollection

时间:2017-09-11 11:45:04

标签: wpf button 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");
            }
        }
    }
.
.
.

视图模型

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>

View

理想情况下,我希望能够通过选项卡中的文本框进行添加,但它们当前已绑定到selectedCar。

2 个答案:

答案 0 :(得分:1)

您的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);
}

答案 1 :(得分:0)

在您的视图中基本上是XAML,您需要将命令绑定到按钮。 Button具有命令属性。将命令绑定到它 例如

<Button Command={Binding AddCarCommand} CommandParameter="{Binding SelectedCar}">

对于所有这些工作,您必须将view的DataContext属性设置为MainViewModel