双向绑定问题-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");
}
}
您的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}" />