C# 将UserControl绑定到自定义BusyIndicator控件
我需要在加载新视图时关注特定的文本框 解决方案是将这行代码添加到视图的onload事件中:C# 将UserControl绑定到自定义BusyIndicator控件,c#,silverlight-4.0,mvvm,busyindicator,C#,Silverlight 4.0,Mvvm,Busyindicator,我需要在加载新视图时关注特定的文本框 解决方案是将这行代码添加到视图的onload事件中: Dispatcher.BeginInvoke(() => { NameTextBox.Focus(); }); 因此,这对一种观点有效,但对另一种观点无效。我花了一些时间调试这个问题,并意识到我正在处理的新视图有一个BusyIndicator,它将焦点从所有控件上移开,因为BusyIndicator设置为true和false是在onload事件之后发生的 因此,解决方案是在将my BusyIndi
Dispatcher.BeginInvoke(() => { NameTextBox.Focus(); });
因此,这对一种观点有效,但对另一种观点无效。我花了一些时间调试这个问题,并意识到我正在处理的新视图有一个BusyIndicator,它将焦点从所有控件上移开,因为BusyIndicator设置为true和false是在onload事件之后发生的
因此,解决方案是在将my BusyIndicator设置为false后,调用焦点到NameTextBox
。我的想法是创建一个可重用的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>
更新2 我需要将
UserControl
更改为Control
,因为我需要将焦点设置为TextBox
对象(实现Control
)。但是,这并不能解决问题。@Matt,不确定
DataContext="{Binding RelativeSource={RelativeSource Self}}"
将在Silverlight 5中工作,您是否尝试将其绑定为静态资源?如果视图中没有
总线指示器,解决焦点问题的常见解决方案是添加代码
Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
到视图的已加载事件。即使存在BusyIndicator
时,这实际上也有效;但是,BusyIndicator
会立即将焦点从Silverlight控件的其余部分移开。解决方案是在BusyIndicator
不忙后调用控件的Focus()
方法
我可以通过这样的控制来解决这个问题:
public class EnhancedBusyIndicator : BusyIndicator
{
public EnhancedBusyIndicator()
{
Loaded += new RoutedEventHandler(EnhancedBusyIndicator_Loaded);
}
void EnhancedBusyIndicator_Loaded(object sender, RoutedEventArgs e)
{
AllowedToFocus = true;
}
private readonly DependencyProperty AllowedToFocusProperty = DependencyProperty.Register("AllowedToFocus", typeof(bool), typeof(EnhancedBusyIndicator), new PropertyMetadata(true));
public bool AllowedToFocus
{
get { return (bool)GetValue(AllowedToFocusProperty); }
set { SetValue(AllowedToFocusProperty, value); }
}
public readonly DependencyProperty ControlToFocusOnProperty = DependencyProperty.Register("ControlToFocusOn", typeof(Control), typeof(EnhancedBusyIndicator), null);
public Control ControlToFocusOn
{
get { return (Control)GetValue(ControlToFocusOnProperty); }
set { SetValue(ControlToFocusOnProperty, value); }
}
protected override void OnIsBusyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnIsBusyChanged(e);
if (AllowedToFocus && !IsBusy)
{
Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
AllowedToFocus = false;
}
}
}
要使用它,请将xaml中的BusyIndicator
标记替换为新的EnhancedBusyIndicator
,并添加适当的命名空间
在元素内部添加一个新属性,ControlToFocusOn
,并将其绑定到视图中的一个现有元素,在EnhancedBusyIndicator
消失后,您希望焦点集中在该元素上:
<my:EnhancedBusyIndicator
ControlToFocusOn="{Binding ElementName=NameTextBox}"
...
>
...
</my:EnhancedBusyIndicator>
当AllowedToFocus
设置为true时,下次EnhancedBusyIndicator
从忙切换到不忙时,焦点将转到ControlToFocusOn
加载视图时,AllowedToFocus也可以设置为false,以防止焦点转到控件。如果将AllowedToFocus
绑定到ViewModel属性,则可能需要更改绑定模式。默认情况下,它是一次性的
我实际上使用的是Silverlight 4;我只是能够通过使用VisualStudio10的Silverlight 5工具来获得我在“Update 1”中发布的更好的错误消息,这也恰好适用于Silverlight 4。我没有尝试将其绑定为静态资源。我试试看。
<my:EnhancedBusyIndicator
ControlToFocusOn="{Binding ElementName=NameTextBox}"
...
>
...
</my:EnhancedBusyIndicator>
<my:EnhancedBusyIndicator
ControlToFocusOn="{Binding ElementName=NameTextBox}"
AllowedToFocus="{Binding IsAllowedToFocus}"
...
>
...
</my:EnhancedBusyIndicator>