双向绑定问题-PropertyChanged&;CanExecuteChanged

本文关键字:amp CanExecuteChanged -PropertyChanged 绑定 问题 | 更新日期: 2023-09-27 18:27:25

我想实现当文本框值发生更改时,我的Add按钮将可用。

我将文本框与视图绑定型号:

<TextBox Name="nameTbx" Text="{Binding Path=NewNode.Name, Mode=TwoWay}" />

我的按钮:

<Button Content="Add" Command="{Binding Path=AddNewNodeProperty}"/>

在XAML代码中,我将DataContext设置为ViewModel。ViewModel看起来像:

/* code*/
private Node _newNode = new Node();
public Node NewNode
{
    get
    {
        return _newNode;
    }
    set
    {
        _newNode = value;
        OnPropertyChanged("NewNode");
    }
}
private AddNode _addNewNodeProperty;
    public AddNode AddNewNodeProperty
    {
        get
        {
            return _addNewNodeProperty;
        }
    }

在构造函数中,我初始化_addNewNodeProperty

this._addNewNodeProperty = new AddNode(this);

这是我的AddNode类:

public class AddNode : ICommand
{
    private ServiceMapViewModel viewModel;
    public AddNode(ServiceMapViewModel viewModel)
    {
        this.viewModel = viewModel;
        this.viewModel.PropertyChanged += (s, e) =>
        {
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, new EventArgs());
            }
        };
    }
    public bool CanExecute(object parameter)
    {
        bool b = !string.IsNullOrWhiteSpace(this.viewModel.NewNode.Name);
        return b;
    }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {
        this.viewModel.AddNewNode();
    }
}

最后是我的Node类:

public class Node
{
    public string Name { get; set; }
    public bool? IsChecked { get; set; }
    public Group Group { get; set; }
    public Category Category { get; set; }
    public string Metadata { get; set; }
    public List<string> Children = new List<string>();
    public List<string> Parents = new List<string>();
}

问题是,当我更改文本框文本时,NewNode会为我获取值,但它应该设置。

Tnx处于高级!

编辑让我补充一下:

我在屏幕上还有一个数据网格,当所选项目更改时,我的添加按钮就可用了。

所选项目:

<DataGrid Name="nodeDataGrid" ItemsSource="{Binding Path=MyServiceMap.Nodes}"
        Background="Silver" Margin="0,34,10,10" IsReadOnly="True" SelectedItem="{Binding Path=SelectedNode}"  >

和VM:

private Node _selectedNode = new Node();
    public Node SelectedNode
    {
        get
        {
            return _selectedNode;
        }
        set
        {
            _selectedNode = value;
            OnPropertyChanged("SelectedNode");
        }
    }

双向绑定问题-PropertyChanged&;CanExecuteChanged

您的TextBox绑定到Node对象的Name属性。Name属性更改时不会引发PropertyChanged事件。更改事件时,只有整个NewNode属性才会引发该事件。

编辑以提供建议

一种方法是创建一个NodeViewModel类,正如mtaboy所建议的那样,该类将实现INotifyPropertyChanged接口。您可以在ViewModel上创建要向用户公开的任何属性。您可以将ViewModel视为位于Model(即Node类)和View(显示给用户的UI)之间。

我建议的一个更改是将ICommand逻辑封装到它自己的类中。我经常使用的是RelayCommand类,它可以在Josh Smith在MSDN上的MVVM文章中找到。如果使用该类,则可以在ViewModel类中定义属性或私有方法,该方法将返回用户是否可以Add。例如,

private bool CanAddNewNode()
{
  return !String.IsNullOrWhitespace(Name);
}

在实例化RelayCommand时,可以为引用上面方法的第二个参数传递lambda。

var saveCommand = new RelayCommand(param => SaveMethod(), param => CanAddNewNode());

您将从ViewModel中公开一个ICommand属性,该属性将返回RelayCommand对象。

希望这能让你开始。

您的节点类必须暗示

INotifyPropertyChanged

public class Node:INotifyPropertyChanged
{
       #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
     string _name ;
      public string Name
      {
          get { return _name; }

          set
          {
              _name = value;
               OnPropertyChanged("Name");
          }
      }

.....

有关更多信息,请参阅MVVM模式

问题是,当我更改文本框文本时,NewNode价值对我来说,但它应该设置。

我认为您也应该支持Node类的INotifyPropertyChanged接口。

此外,如果您想在每个字符更新时保持项目同步,请尝试设置UpdateSourceTrigger,否则属性将在LostFocus事件中更新。

<TextBox Name="nameTbx" 
         Text="{Binding Path=NewNode.Name, 
                        Mode=TwoWay,
                        UpdateSourceTrigger=PropertyChanged}" />