无法聚焦驻留在DataTemplate中的按钮

时间:2012-02-07 14:43:30

标签: wpf binding styles

我有一个位于扩展工具包BusyIndi​​cator控件上的DataTemplate中的按钮。我有一个数据触发器(我尝试过一个样式触发器)绑定到BusyIndi​​cator控件的可见性,以便在BusyIndi​​cator可见时让FocusManager将焦点设置到按钮上。
这不起作用。我还尝试在BusyIndi​​cator上处理IsVisibleChanged事件,通过遍历可视化树将焦点设置在代码隐藏中的按钮上,这也不起作用。是否有一些特殊方法可以将键盘焦点设置在按钮上?

2 个答案:

答案 0 :(得分:1)

我想我遇到了同样的问题。这是我使用的代码:

public delegate void SimpleDelegate();
private void grid_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (grid.Visibility == System.Windows.Visibility.Visible)
    {
        TextBox tb = (TextBox)(sender as Grid).FindName("theTextbox");

        tb.SelectAll();
        Dispatcher.BeginInvoke(DispatcherPriority.Input, new SimpleDelegate(delegate { tb.Focus(); }));
    }
}

此代码还会在显示包含文本框的网格时选择所有文本。

也许有更好的方法,但使用Dispatcher设置焦点似乎对我有用。

答案 1 :(得分:0)

This SO article描述了如何在ItemsControl中选择项目的容器并导航树以选择要更改的项目(在这种情况下将其聚焦)。

从下面修改我的代码:

public void WhateverMethodForShowingBusy ()
{
    //Get a reference to your View
    FrameworkElement myView = this.View;  // I generally have a reference to the view living on the ViewModel set at construction time
    // Get a reference to your ItemsControl - in this example by name
    ListBox custListBox = myView.ListBoxName;
    // Get the currently selected Item which will be a CustomerViewModel 
    // (not a DataTemplate or ListBoxItem)
    CustomerViewModel cvm = custListBox.SelectedItem;

    //Generate the ContentPresenter
    ContentPresenter cp = custListBox.ItemContainerGenerator.ContainerFromItem(cvm) as ContentPresenter;

    //Now get the button and focus it.
    Button myButton = cp.FindName("MyButtonName");
    myButton.Focus();
}

以下信息根据IsFocused是设置焦点的读/写属性的错误而不正确。它不适用。

这是MVVM真正运作良好的另一个地方。如果您不熟悉MVVM,我强烈建议您进行调查。它解决了很多这样的问题,如果实施得当,它可以使你的代码更易于维护。

如果您正在使用MVVM方法,只需在位于DataTemplate后面的ViewModel上托管一个布尔属性(我们称之为IsFocused)。例如,我们有一个Customer类,一个CustomerViewModel类,它包含一个customer实例,然后是MainViewModel,它包含一组CustomerViewModel。 ItemsControl的ItemsSource属性绑定到CustomerViewModels集合,DataTemplate按钮的IsFocused属性绑定到CustomerViewModel上的IsFocused属性。

我不确定您的工作流程,但您基本上可以这样做:

public void WhateverMethodForShowingBusy ()
{
    //Get a reference to your View
    FrameworkElement myView = this.View;  // I generally have a reference to the view living on the ViewModel set at construction time
    // Get a reference to your ItemsControl - in this example by name
    ListBox custListBox = myView.ListBoxName;
    // Get the currently selected Item which will be a CustomerViewModel 
    // (not a DataTemplate or ListBoxItem)
    CustomerViewModel cvm = custListBox.SelectedItem;

    //Finally set the property.
    cvm.IsFocused = true;
}

与MVVM中的所有内容一样,请确保您正在实现INotifyPropertyChanged。