我想实现在更改文本框值时,我的“添加”按钮变为可用。
我用viewModel绑定文本框:
<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 in advanced!
修改 让我补充一点:
我在屏幕上也有一个数据网格,当更改了选定项目时,我的添加按钮变为可用。
选择项目:
<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");
}
}
答案 0 :(得分:1)
问题在于,当我更改文本框文本时,NewNode正在获取 我的价值,但它应该设定。
我相信您也应该支持INotifyPropertyChanged
类的Node
界面。
此外,如果你想在每个角色更新时保持同步 - 尝试设置UpdateSourceTrigger,否则属性将在LostFocus事件上更新。
<TextBox Name="nameTbx"
Text="{Binding Path=NewNode.Name,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
答案 1 :(得分:1)
您的TextBox绑定到Name
对象的Node
属性。 Name
属性在更改时不会引发PropertyChanged
事件。只有整个NewNode
属性会在事件发生变化时引发事件。
修改以提供建议
一种方法是创建一个NodeViewModel
类,正如 mtaboy 建议的那样,它将实现INotifyPropertyChanged
接口。您将在ViewModel上创建要向用户公开的任何属性。您可以将ViewModel视为模型(即Node
类)和View(显示给用户的UI)之间的对象。
我建议的一个改变是将ICommand
逻辑封装到自己的类中。我经常使用的是RelayCommand
类,可以在MSDN上的Josh Smith的MVVM article中找到。如果使用该类,则可以在ViewModel类中定义属性或私有方法,该方法将返回用户是否可以添加。例如,
private bool CanAddNewNode()
{
return !String.IsNullOrWhitespace(Name);
}
在实例化RelayCommand
时,您可以为引用上述方法的第二个参数传递lambda。
var saveCommand = new RelayCommand(param => SaveMethod(), param => CanAddNewNode());
您将从ViewModel公开ICommand
属性,该属性将返回RelayCommand
对象。
希望这能让你开始。
答案 2 :(得分:1)
您的节点类必须恭维
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 Pattern