Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将ICommand绑定到按钮?_C#_Wpf_Mvvm - Fatal编程技术网

C# 将ICommand绑定到按钮?

C# 将ICommand绑定到按钮?,c#,wpf,mvvm,C#,Wpf,Mvvm,我是MVVM模式的新手,事情进展非常缓慢,我希望能够单击表单上的按钮,然后在运行时动态创建一个文本框。我有一个“添加标题”和“添加问题”,它们都添加了文本框,但在不同的位置,你可以在一个标题下添加尽可能多的问题。我在这个类中创建了一个名为Standard的类,它包含: public class Standard { string _title; ObservableCollection<string> _questions; public event Prop

我是MVVM模式的新手,事情进展非常缓慢,我希望能够单击表单上的按钮,然后在运行时动态创建一个文本框。我有一个“添加标题”和“添加问题”,它们都添加了文本框,但在不同的位置,你可以在一个标题下添加尽可能多的问题。我在这个类中创建了一个名为
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}"/>