У меня есть требование сосредоточиться на конкретном текстовом поле при загрузке нового представления.
Решением было добавить эту строку кода в событие OnLoaded для представления:
Dispatcher.BeginInvoke(() => { NameTextBox.Focus(); });
Так что это работало для одного представления, но не для другого. Я потратил некоторое время на отладку проблемы и понял, что в новом представлении, над которым я работал, был BusyIndicator, который отвлекает внимание от всех элементов управления, так как для BusyIndicator было установлено значение true, а false происходило после события OnLoaded.
Таким образом, решение состоит в том, чтобы вызвать фокус на NameTextBox
после того, как мой BusyIndicator был установлен в false. Моя идея состояла в том, чтобы создать повторно используемый элемент управления BusyIndicator, который обрабатывает эту дополнительную работу. Однако у меня возникают проблемы с этим в MVVM.
Я начал с простого расширения набора инструментов: BusyIndicator:
public class EnhancedBusyIndicator : BusyIndicator
{
public UserControl ControlToFocusOn { get; set; }
private bool _remoteFocusIsEnabled = false;
public bool RemoteFocusIsEnabled
{
get
{
return _remoteFocusIsEnabled;
}
set
{
if (value == true)
EnableRemoteFocus();
}
}
private void EnableRemoteFocus()
{
if (ControlToFocusOn.IsNotNull())
Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
else
throw new InvalidOperationException("ControlToFocusOn has not been set.");
}
Я без проблем добавил элемент управления в свой XAML-файл:
<my:EnhancedBusyIndicator
ControlToFocusOn="{Binding ElementName=NameTextBox}"
RemoteFocusIsEnabled="{Binding IsRemoteFocusEnabled}"
IsBusy="{Binding IsDetailsBusyIndicatorActive}"
...
>
...
<my:myTextBox (this extends TextBox)
x:Name="NameTextBox"
...
/>
...
</my:EnhancedBusyIndicator>
Таким образом, идея заключается в том, что когда IsRemoteFocusEnabled
установлен в true в моей ViewModel (что я делаю после того, как я установил IsBusy
в false в ViewModel), фокус будет установлен на NameTextBox
. И если это сработает, другие могут использовать EnhancedBusyIndicator
и просто привязать к другому элементу управления и соответствующим образом включить фокус в своих собственных моделях представления, при условии, что их представления имеют начальную BusyIndicator
активную.
Однако я получаю это исключение при загрузке представления:
Установка свойства 'foo.Controls.EnhancedBusyIndicator.ControlToFocusOn' вызвала исключение. [Линия: 45 Позиция: 26]
Будет ли это решение работать? Если так, что не так с тем, что у меня есть (не могу установить свойство ControlToFocusOn
)?
Обновление 1
Я установил Visual Studio 10 Tools для Silverlight 5 и получил лучшее сообщение об ошибке при переходе к новому представлению. Теперь я получаю это сообщение об ошибке:
«System.ArgumentException: объект типа System.Windows.Data.Binding не может быть преобразован в тип System.Windows.Controls.UserControl»
Кроме того, я думаю, что мне нужно изменить DataContext для этого элемента управления. В конструкторе с выделенным кодом для DataContext установлено значение моего ViewModel. Я попытался добавить свойство DataContext к EnhancedBusyIndicator
, но это не сработало:
<my:EnhancedBusyIndicator
DataContext="{Binding RelativeSource={RelativeSource Self}}"
ControlToFocusOn="{Binding ElementName=NameTextBox}"
RemoteFocusIsEnabled="{Binding IsRemoteFocusEnabled}"
IsBusy="{Binding IsDetailsBusyIndicatorActive}"
...
>
Обновление 2
Мне нужно изменить UserControl
на Control
, так как я хочу установить фокус на TextBox
объекты (которые реализуют Control
). Однако это не решает проблему.