【问题标题】:WPF Object not NULL on check, but Properties NULL检查时 WPF 对象不为 NULL,但属性为 NULL
【发布时间】:2016-04-14 10:18:00
【问题描述】:

我正在构建我的第一个 WPF 程序,使用 RelayCommand 并单击按钮以传递“用户”对象作为参数来编辑或创建用户。现有用户可以很好地传递给 onClick,但在空白行中为新用户输入的信息始终具有 NULL 属性。但是,检查对象是否为 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));
        }
    }
}

中继命令:

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
}

从主窗口打开用户窗口:

UsersViewModel Usersvm = new UsersViewModel();
Usersvm.Users = new ObservableCollection<UserViewModel>();
Usersvm.Users.Add(new UserViewModel() { FirstName = "John", LastName = "Doe", EMail = "JohnDoe@yahoo.com", 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>

【问题讨论】:

    标签: c# wpf xaml object data-binding


    【解决方案1】:

    颠倒你做事的顺序。首先检查确定 obj 是否为空。如果(且仅当)它是 not null 则将其转换(转换)为关联的 ViewModel。然后检查 associatedViewModel 是否为空。那么如果(且仅当) associatedViewModel 不为空,您可以使用 associatedViewModel.LastName。如果其中一个为空,当然会发出错误。

    假设存在不应该为 null 的内容,请将代码减少到重现问题所需的最低限度。

    【讨论】:

      【解决方案2】:

      这里的答案是 DataGrid 总是将原始值发送到按钮单击。将用户引导到可以通过绑定的文本框编辑单个对象的新页面解决了这个问题。

      【讨论】:

      • 你是怎么发现的?我希望你至少做出了我建议的修改,并将继续做这种事情。我假设您在进行了我指出的修改之后发现了问题。
      • 这个问题源于我之前遇到的问题stackoverflow.com/questions/36555191/wpf-listbox-data-binding/…。我用该线程上的一张海报进行了询问,我们解决了它。感谢您的回复和关注!我做了你建议的改变,这很有意义。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-23
      • 2017-02-17
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多