如何在WPF(MVVM)中接收对控件的引用?

如何在WPF(MVVM)中接收对控件的引用?,wpf,mvvm,reference,Wpf,Mvvm,Reference,在我的WPF MVVM项目中,我有一个按钮,可以触发一个函数,该函数应该向xml添加一个节点,然后将焦点设置为文本框。 我的问题是,如何接收对控件的引用 视图: 不要在ViewModel中执行此操作。ViewModel不应该知道有关视图的任何信息 您可以在代码隐藏中执行此操作: 在代码隐藏中处理TreeView.SelectedItemChanged事件,并更新ViewModel上的SelectedItem属性。您还可以使用附加的行为来执行此操作 要聚焦文本框,请从ViewModel引发事件并在

在我的WPF MVVM项目中,我有一个按钮,可以触发一个函数,该函数应该向xml添加一个节点,然后将焦点设置为文本框。 我的问题是,如何接收对控件的引用

视图:

不要在ViewModel中执行此操作。ViewModel不应该知道有关视图的任何信息

您可以在代码隐藏中执行此操作:

在代码隐藏中处理TreeView.SelectedItemChanged事件,并更新ViewModel上的SelectedItem属性。您还可以使用附加的行为来执行此操作

要聚焦文本框,请从ViewModel引发事件并在代码隐藏中处理它:

视图模型:

代码隐藏:

您可以使用附加属性来处理确保文本框接收焦点

<DataTemplate DataType="{x:Type YourViewModel}">
    <Grid FocusManager.FocusedElement="{Binding ElementName=userInput}">
       <TextBox x:Name="userInput" />
    </Grid>
</DataTemplate>

至于你的第二部分文本框。SelectAll你可能需要对自己的行为或附加属性进行处理,以一次性处理聚焦和选择。

TreeView不能很好地处理MVVM,不幸的是…@Will,实际上他们可以很好地处理MVVM,但这需要一些工作。。。我使用了一个附加的行为,使得绑定SelectedItem相对容易。另见JoshSmith@ThomasLevesque:lurl,让我做一些工作,以获得与其他控件相同的功能,但我觉得这并不是很好。@Will,这是一个可重用的解决方案,你只需要做一次…@ThomasLevesque:在你的每一个产品中都有一个treeview。哎哟。
RelayCommand buttonAddCategory_Click;
public ICommand ButtonAddCategory_Click
{
    get
    {
        return buttonAddCategory_Click ?? (buttonAddCategory_Click = new RelayCommand(param => this.AddCategory(),
                                                                                      param => true));
    }
}

public void AddCategory()
{
    ...
    //get the "node" -> reference?
    XmlNode selectedItem = (XmlNode)treeView.SelectedItem;
    ..
    //add the node to the xml
    ..
    //change focus -> reference?
    textBoxTitel.Focus();
    textBoxTitel.SelectAll();
}
public XmlNode SelectedItem { get; set; }

public event EventHandler FocusTitle;

public void AddCategory()
{
    ...
    //get the "node" -> reference?
    XmlNode selectedItem = this.SelectedItem;
    ..
    //add the node to the xml
    ..
    // Notify the view to focus the TextBox
    if (FocusTitle != null)
        FocusTitle(this, EventArgs.Empty);

}
// ctor
public MyView()
{
    InitializeComponent();
    DataContextChanged += MyView_DataContextChanged;
}

private void MyView_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    MyViewModel vm = (MyViewModel)e.NewValue;
    vm.FocusTitle += ViewModel_FocusTitle;
}

private void TreeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventHandler<Object> e)
{
    MyViewModel vm = (MyViewModel)DataContext;
    vm.SelectedItem = (XmlNode)e.NewValue;
}

private void ViewModel_FocusTitle(object sender, EventArgs e)
{
    textBoxTitle.Focus();
}
<DataTemplate DataType="{x:Type YourViewModel}">
    <Grid FocusManager.FocusedElement="{Binding ElementName=userInput}">
       <TextBox x:Name="userInput" />
    </Grid>
</DataTemplate>