C# 将ICommand绑定到按钮?
我是MVVM模式的新手,事情进展非常缓慢,我希望能够单击表单上的按钮,然后在运行时动态创建一个文本框。我有一个“添加标题”和“添加问题”,它们都添加了文本框,但在不同的位置,你可以在一个标题下添加尽可能多的问题。我在这个类中创建了一个名为C# 将ICommand绑定到按钮?,c#,wpf,mvvm,C#,Wpf,Mvvm,我是MVVM模式的新手,事情进展非常缓慢,我希望能够单击表单上的按钮,然后在运行时动态创建一个文本框。我有一个“添加标题”和“添加问题”,它们都添加了文本框,但在不同的位置,你可以在一个标题下添加尽可能多的问题。我在这个类中创建了一个名为Standard的类,它包含: public class Standard { string _title; ObservableCollection<string> _questions; public event Prop
Standard
的类,它包含:
public class Standard
{
string _title;
ObservableCollection<string> _questions;
public event PropertyChangedEventHandler PropertyChanged;
#region NofiftyPropChnage
protected void NotifyOfPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
protected void NotifyOfPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
{
NotifyOfPropertyChanged(property.GetMemberInfo().Name);
}
#endregion
#region Properties
public string Title
{
get { return _title; }
set
{
_title = value;
NotifyOfPropertyChanged(() => Title);
}
}
public ObservableCollection<string> Questions
{
get { return _questions; }
set
{
_questions = value;
NotifyOfPropertyChanged(() => Questions);
}
}
#endregion
}
此类包含一个标准列表,当您单击“保存”,文本框和文本框中的信息都已完成时,即为标准。它保存为标准
最后,我的XAML代码:
<Grid>
<button Content="Add Title"/>
<button Content="Add Question"/>
<StackPanel>
<ItemsControl ItemsSource="{Binding StandardCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:Standard}">
<Grid>
<TextBox Text="{Binding Title}"/>
<ItemsControl ItemsSource="{Binding Questions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Questions}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
一切都在运行,没有错误,但当我单击“添加标题”或“添加问题”时,没有文本框出现,是否有帮助?尝试在类
标准上实现INotifyPropertyChanged
public class Standard : INotifyPropertyChanged
{
string _title;
ObservableCollection<string> _questions;
public event PropertyChangedEventHandler PropertyChanged;
#region NofiftyPropChnage
protected void NotifyOfPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
protected void NotifyOfPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
{
NotifyOfPropertyChanged(property.GetMemberInfo().Name);
}
#endregion
#region Properties
public string Title
{
get { return _title; }
set
{
_title = value;
NotifyOfPropertyChanged(() => Title);
}
}
public ObservableCollection<string> Questions
{
get { return _questions; }
set
{
_questions = value;
NotifyOfPropertyChanged(() => Questions);
}
}
#endregion
}
公共类标准:INotifyPropertyChanged
{
字符串标题;
可观察收集问题;
公共事件属性更改事件处理程序属性更改;
#区域性技术
受保护的void NotifyOfPropertyChanged(字符串名称)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(此,新PropertyChangedEventArgs(名称));
}
}
受保护的void NotifyOfPropertyChanged(表达式属性)
{
NotifyOfPropertyChanged(property.GetMemberInfo().Name);
}
#端区
#区域属性
公共字符串标题
{
获取{return\u title;}
设置
{
_标题=价值;
财产变更通知(()=>名称);
}
}
公开收集问题
{
获取{返回_问题;}
设置
{
_问题=价值;
财产变更通知(()=>问题);
}
}
#端区
}
尝试在类标准上实现INotifyPropertyChanged
public class Standard : INotifyPropertyChanged
{
string _title;
ObservableCollection<string> _questions;
public event PropertyChangedEventHandler PropertyChanged;
#region NofiftyPropChnage
protected void NotifyOfPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
protected void NotifyOfPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
{
NotifyOfPropertyChanged(property.GetMemberInfo().Name);
}
#endregion
#region Properties
public string Title
{
get { return _title; }
set
{
_title = value;
NotifyOfPropertyChanged(() => Title);
}
}
public ObservableCollection<string> Questions
{
get { return _questions; }
set
{
_questions = value;
NotifyOfPropertyChanged(() => Questions);
}
}
#endregion
}
公共类标准:INotifyPropertyChanged
{
字符串标题;
可观察收集问题;
公共事件属性更改事件处理程序属性更改;
#区域性技术
受保护的void NotifyOfPropertyChanged(字符串名称)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(此,新PropertyChangedEventArgs(名称));
}
}
受保护的void NotifyOfPropertyChanged(表达式属性)
{
NotifyOfPropertyChanged(property.GetMemberInfo().Name);
}
#端区
#区域属性
公共字符串标题
{
获取{return\u title;}
设置
{
_标题=价值;
财产变更通知(()=>名称);
}
}
公开收集问题
{
获取{返回_问题;}
设置
{
_问题=价值;
财产变更通知(()=>问题);
}
}
#端区
}
标准需要实现INotifyPropertyChanged接口。通常情况下,您不应该多次这样做,只需声明一个实现这些内容的基类,并从中继承所有视图模型。另外,如果您使用package manager将MVVM Lite添加到您的项目中,那么您将获得大量这方面的内容。标准需要实现INotifyPropertyChanged接口。通常情况下,您不应该多次这样做,只需声明一个实现这些内容的基类,并从中继承所有视图模型。另外,如果您使用package manager将MVVM Lite添加到您的项目中,那么您将获得大量这方面的信息。我不知道为什么其他人会喋喋不休地谈论INotifyPropertyChanged
接口,因为这与ICommand
关系不大,尽管您似乎试图使用它,但没有将其添加到标准
类定义中
无论哪种方式,我觉得您都需要使用RelayCommand
或类似的命令。这是一个扩展ICommand
接口的类。。。您可以将其视为一个委托
命令。您可以简单地定义命令逻辑和canExecute
内联处理程序,而不是为每个命令定义单独的类。以下是一个简化的示例:
public ICommand SaveCommand
{
get { return new RelayCommand(execute => Save(), canExecute => CanSave()); }
}
...
<Button Content="Save" Command="{Binding SaveCommand}" />
public ICommand SaveCommand
{
获取{returnnewrelaycommand(execute=>Save(),canExecute=>CanSave());}
}
...
你可以在GitHub的页面上找到它的实现,在MDSN杂志的页面上找到它的描述。我不知道为什么其他人在谈论INotifyPropertyChanged
接口,因为这与ICommand
关系不大,尽管您似乎试图使用它,但没有将其添加到标准
类定义中
无论哪种方式,我觉得您都需要使用RelayCommand
或类似的命令。这是一个扩展ICommand
接口的类。。。您可以将其视为一个委托
命令。您可以简单地定义命令逻辑和canExecute
内联处理程序,而不是为每个命令定义单独的类。以下是一个简化的示例:
public ICommand SaveCommand
{
get { return new RelayCommand(execute => Save(), canExecute => CanSave()); }
}
...
<Button Content="Save" Command="{Binding SaveCommand}" />
public ICommand SaveCommand
{
获取{returnnewrelaycommand(execute=>Save(),canExecute=>CanSave());}
}
...
您可以在GitHub的页面上找到它的实现,在MDSN杂志的页面上找到它的描述。好的,我将再次尝试这一点。我已经去掉了标题的一部分
// by Josh Smith, http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
public class MyViewModel : ObservableObject
{
public ICommand AddQuestionCommand {get; private set;}
ObservableCollection<string> _questions = new ObservableCollection<string>();
public ObservableCollection<string> Questions
{
get { return _questions; }
set
{
_questions = value;
OnPropertyChanged(() => Questions);
}
}
public MyViewModel()
{
this.AddQuestionCommand = new RelayCommand(new Action<object>((o) => OnAddQuestion()));
}
private void OnAddQuestion()
{
this.Questions.Add("new item");
}
}
<StackPanel>
<Button Content="Add Question" Command="{Binding AddQuestionCommand}" HorizontalAlignment="Left"/>
<ItemsControl ItemsSource="{Binding Questions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding .}" Width="200" HorizontalAlignment="Left"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
public class RelayCommand : ICommand
{
public Func<bool> CanExecute { get; set; }
public Action Execute { get; set; }
public RelayCommand()
{
}
public RelayCommand(Action execute)
{
Execute = execute;
}
#region ICommand Members
bool ICommand.CanExecute(object parameter)
{
if (this.CanExecute == null)
{
return true;
}
else
{
return this.CanExecute();
}
}
event EventHandler ICommand.CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
void ICommand.Execute(object parameter)
{
this.Execute();
}
#endregion
}
public ICommand AddTitle { get; private set; }
public ICommand AddQuestion { get; private set; }
public ViewModel()
{
_standardCollection = new ObservableCollection<Standard>();
AddTitle = new RelayCommand(OnAddTitle);
AddQuestion = new RelayCommand(OnAddQuestion);
}
void OnAddTitle()
{
_standardCollection.Add(new Standard());
}
void OnAddQuestion()
{
_standardCollection.Last().Questions.Add(new Question("Some Question"));
}
<Button Content="Add Title" Command="{Binding AddTitle}"/>
<Button Content="Add Question" Command="{Binding AddQuestion}"/>