2017-09-11 22 views
1

WPF 및 MVVM 패턴 세계에 새로운 기능이 추가되었습니다. 누군가가 버튼을 눌러 속성을 설정하고 명령을 설정하기 위해 텍스트 상자를 사용하여 observableColllection에 새 객체를 만들고 추가 할 수있는 방법에 대한 간단한 설명을 제공 할 수 있기를 바랍니다.WPF MVVM 텍스트 상자 및 ICommand를 사용하여 ObservableCollection에 새 객체 추가

내가 지금까지 가지고 :

모델

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에 바인딩되어 있습니다.

+0

자습서를 시청하는 것이 좋습니다. – berthos

+0

많이 지켜보고 있었지만 나에게 도움이되는 것을 찾지 못했습니다. – Nathan

+0

가장 간단한 mvvm 예 https://github.com/MarkWithall/worlds-simplest-csharp-wpf-mvvm-example – tetralobita

답변

1

귀하의 RelayCommand 당신의 AddCar 메소드를 호출한다 소스 컬렉션의 객체 :

private void AddCar(object o) 
{ 
    CarRegistry.Add(new CarModel { Model = Car.Model }); 
} 
뷰에서 6,

, 당신은 자동차 개체의 속성에 TextBoxes을 결합 수 :

<TextBox Text="{Binding Car.Model, UpdateSourceTrigger=PropertyChanged}" /> 

을 ...하고 명령 속성에 Button :

<Button Command="{Binding AddCarCommand}" /> 

뷰의 DataContext 설정하는 것을 잊지 마십시오

public MainWindow() 
{ 
    InitializeComponent(); 
    DataContext = new MainViewModel(); 
} 

을 ... 실제로 뷰 모델에 somwhere Car 개체를 만듭니다 :

private CarModel _car = new CarModel(); 

편집 :

01 명령의메소드는 _execute 액션을 호출해야합니다.

public void Execute(object parameter) 
{ 
    _execute(parameter); 
} 
+0

감사합니다! 나는 그것을 시도 할 것이다. – Nathan

+0

아니요. 입력란이 바인딩되지 않았거나 RelyCommand에 문제가 있습니다. 지금 바인딩을 시도하고 디버깅하려고합니다. 이후에 업데이트를 게시하십시오. – Nathan

+0

Car 클래스 및 AddCar 메서드의 setter에 중단 점을 넣습니다. 그들이 맞았습니까? – mm8

0

기본적으로 XAML에서는 명령을 단추에 바인딩해야합니다. 버튼에 명령 속성이 있습니다. 예를 들어 에 바인딩 명령. 새 Car를 추가하려면이 방법에서는

public ICommand AddCarCommand 
{ 
    get 
    { 
     if (_addCarCommand == null) 
     { 
      _addCarCommand = new RelayCommand(param => AddCar(param), param => true); 
     } 
     return _addCarCommand; 
    } 
} 

: 모든이를 위해

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

당신이 MainViewModel에보기의 DataContext에 속성을 설정 한 작업