2016-04-13 28 views
0

我正在構建我的第一個WPF程序使用RelayCommand和按鈕單擊傳遞一個「用戶」對象作爲參數編輯或創建用戶。現有用戶傳遞給onClick的罰款,但在新行中爲新用戶輸入的信息始終具有NULL屬性。但是,檢查對象是否爲NULL的測試總是表示該對象不是。對象怎麼可能不是NULL,但它的內容是在窗口中輸入的?任何人都可以發現新對象上的綁定有問題嗎?提前謝謝了!WPF對象不檢查NULL,但屬性NULL

UserViewModel類:

public class UserViewModel : INotifyPropertyChanged 
{ 
    private string _FirstName; 
    public string FirstName 
    { 
     get { return _FirstName; } 
     set { _FirstName = value; NotifyPropertyChanged("FirstName"); } 
    } 

    private string _LastName; 
    public string LastName 
    { 
     get { return _LastName; } 
     set { _LastName = value; NotifyPropertyChanged("LastName"); } 
    } 

    private string _EMail; 
    public string EMail 
    { 
     get { return _EMail; } 
     set { _EMail = value; NotifyPropertyChanged("EMail"); } 
    } 

    private int _UserID; 
    public int UserID 
    { 
     get { return _UserID; } 
     set { _UserID = value; NotifyPropertyChanged("UserID"); } 
    } 

    private string _Position; 
    public string Position 
    { 
     get { return _Position; } 
     set { _Position = value; NotifyPropertyChanged("Position"); } 
    } 

    private DateTime? _EndDate; 
    public DateTime? EndDate 
    { 
     get { return _EndDate; } 
     set { _EndDate = value; NotifyPropertyChanged("EndDate"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

UsersViewModel類:

public partial class UsersViewModel : INotifyPropertyChanged 
{ 
    public RelayCommand<object> editButton_Click_Command { get; set; } 

    public UsersViewModel() 
    { 
     editButton_Click_Command = new RelayCommand<object>(OneditButton_Click_Command); 
    } 

    private ObservableCollection<UserViewModel> _Users; 
    public ObservableCollection<UserViewModel> Users 
    { 
     get { return _Users; } 
     set { _Users = value; NotifyPropertyChanged("Users"); } 
    } 

    private void OneditButton_Click_Command(object obj) 
    { 
     var associatedViewModel = obj as UserViewModel; 
     string lastName = associatedViewModel.LastName; //Always NULL on new row entered in Window!!! 
     if (associatedViewModel == null) 
     { 
      //Never reached 
     } 
     if (obj == null) 
     { 
      //Never reached 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
} 

的RelayCommand:

public class RelayCommand<T> : ICommand 
{ 
    #region Fields 

    private readonly Action<T> _execute = null; 
    private readonly Predicate<T> _canExecute = null; 

    #endregion 

    #region Constructors 

    /// <summary> 
    /// Creates a new command that can always execute. 
    /// </summary> 
    /// <param name="execute">The execution logic.</param> 
    public RelayCommand(Action<T> execute) 
     : this(execute, null) 
    { 
    } 

    /// <summary> 
    /// Creates a new command with conditional execution. 
    /// </summary> 
    /// <param name="execute">The execution logic.</param> 
    /// <param name="canExecute">The execution status logic.</param> 
    public RelayCommand(Action<T> execute, Predicate<T> canExecute) 
    { 
     if (execute == null) 
      throw new ArgumentNullException("execute"); 

     _execute = execute; 
     _canExecute = canExecute; 
    } 

    #endregion 

    #region ICommand Members 

    public bool CanExecute(object parameter) 
    { 
     return _canExecute == null ? true : _canExecute((T)parameter); 
    } 

    public event EventHandler CanExecuteChanged 
    { 
     add 
     { 
      if (_canExecute != null) 
       CommandManager.RequerySuggested += value; 
     } 
     remove 
     { 
      if (_canExecute != null) 
       CommandManager.RequerySuggested -= value; 
     } 
    } 

    public void Execute(object parameter) 
    { 
     try 
     { 
      _execute((T)parameter); 
     } 
     catch 
     { 
      System.Windows.MessageBox.Show("Please enter values for the new entry."); 
     } 
    } 

    #endregion 
} 

開口從主窗口的UsersWindow:

UsersViewModel Usersvm = new UsersViewModel(); 
Usersvm.Users = new ObservableCollection<UserViewModel>(); 
Usersvm.Users.Add(new UserViewModel() { FirstName = "John", LastName = "Doe", EMail = "[email protected]", EndDate = new DateTime(2016, 2, 1), Position = "Developer", UserID = 1 }); 
new UsersWindow(Usersvm).Show(); 

UsersWindow.xaml.cs:

public partial class UsersWindow : Window 
{ 
    public UsersWindow(UsersViewModel uvm) 
    { 
     InitializeComponent(); 
     DataContext = uvm; 
    } 
} 

最後的XAML:

<Window x:Name="Base_V" 
    x:Class="DbEntities.UsersWindow" 
    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:DbEntities" 
    xmlns:ViewModels="clr-namespace:DbEntities" 
    xmlns:staticData="clr-namespace:DbEntities" 
    mc:Ignorable="d" 
    Title="UsersWindow" Height="Auto" Width="900"> 
    <Window.Resources> 
     <staticData:PositionsList x:Key="PositionsList" /> 
    </Window.Resources> 
    <Window.DataContext> 
     <ViewModels:UsersViewModel/> 
    </Window.DataContext> 
    <Grid> 
     <DataGrid Name="DataGrid1" ItemsSource="{Binding Users}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" 
       ColumnWidth="*" AutoGenerateColumns="False"> 
      <DataGrid.Columns> 
       <DataGridTemplateColumn> 
        <DataGridTemplateColumn.CellTemplate> 
         <DataTemplate> 
          <Button Command="{Binding DataContext.editButton_Click_Command, ElementName=Base_V}" CommandParameter="{Binding}" >Edit</Button> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellTemplate> 
       </DataGridTemplateColumn> 
       <DataGridTextColumn Header="User ID" Binding="{Binding UserID}" IsReadOnly="True" /> 
       <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" /> 
       <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" /> 
       <DataGridTextColumn Header="E-Mail" Binding="{Binding EMail}" /> 
       <DataGridTemplateColumn> 
        <DataGridTemplateColumn.HeaderTemplate> 
         <DataTemplate> 
          <Label Content="Position" /> 
         </DataTemplate> 
        </DataGridTemplateColumn.HeaderTemplate> 
        <DataGridTemplateColumn.CellTemplate> 
         <DataTemplate> 
          <ComboBox ItemsSource="{StaticResource PositionsList}" SelectedItem="{Binding Position}" /> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellTemplate> 
       </DataGridTemplateColumn> 
       <DataGridTextColumn Header="End Date" Binding="{Binding EndDate, StringFormat={}{0:MM/dd/yyyy}}" /> 
      </DataGrid.Columns> 
     </DataGrid> 
    </Grid> 
</Window> 

回答

0

這裏的答案是DataGrid始終將原始值發送到按鈕單擊。將用戶引導到一個新頁面,在該頁面中可以通過綁定文本框編輯單個對象,從而解決了問題。

+0

你是怎麼發現的?我希望你至少做了我提出的修改,並將繼續做這樣的事情。我會假設你在**進行修改後發現了問題**。 – user34660

+0

此問題源於我以前在此處出現的問題http://stackoverflow.com/questions/36555191/wpf-listbox-data-binding/36558782#36558782。我在那個帖子上詢問了一個海報,我們解決了它。感謝您的迴應和興趣!我做出了您所建議的更改,這些更改是完全合理的。 – jle

0

反向,你正在做的事情的順序。首先檢查以確定obj是否爲空。如果(且僅當)它是非空然後轉換(轉換)它到一個associatedViewModel。然後檢查associatedViewModel是否爲空。那麼,如果(且僅當)關聯ViewModel是非空,您可以使用associatedViewModel.LastName。如果其中任何一個爲空,則發出錯誤。

假設有一些不應該的東西,請將代碼降低到重新創建問題所需的最小值。