绑定用户控件到自定义BusyIndi​​cator控件 [英] Binding a UserControl to a custom BusyIndicator control

查看:169
本文介绍了绑定用户控件到自定义BusyIndi​​cator控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要求,着眼于当一个新的视图被加载特定的文本框。

I have a requirement to focus on a specific textbox when a new view is loaded.

的解决方案是这行代码添加到该的OnLoaded事件观点:

The solution was to add this line of code to the OnLoaded event for the view:

Dispatcher.BeginInvoke(() => { NameTextBox.Focus(); });



所以这个工作了一种观点,而不是其他。我花了一些时间调试问题,并意识到我的工作在新的观点有一个BusyIndi​​cator控件这需要从自BusyIndi​​cator控件被设置为true和false是在OnLoaded事件发生后存在的所有控制集中了。

So this worked for one view, but not another. I spent some time debugging the problem and realized that the new view I was working on had a BusyIndicator that takes focus away from all controls since the BusyIndicator being set to true and false was occuring after the OnLoaded event.

因此,解决方法是调用焦点 NameTextBox 我的BusyIndi​​cator控件已被设置为false。我的想法是创建一个处理这些额外的工作可重复使用BusyIndi​​cator控件。但是,我无法在MVVM这样

So the solution is to call focus to the NameTextBox after my BusyIndicator has been set to false. My idea was to create a reusable BusyIndicator control that handles this extra work. However, I am having trouble doing this in MVVM.

我开始制作工具的简单扩展:BusyIndi​​cator控件:

I started by making a simple extension of the toolkit: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文件:

I added the control to my XAML file with no problem:

<my:EnhancedBusyIndicator
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    RemoteFocusIsEnabled="{Binding IsRemoteFocusEnabled}"
    IsBusy="{Binding IsDetailsBusyIndicatorActive}"
...
>    
...
    <my:myTextBox (this extends TextBox)
        x:Name="NameTextBox"
    ...
    />
...
</my:EnhancedBusyIndicator>



这样的想法是,当设置 IsRemoteFocusEnabled 在我的ViewModel真(这是我做我设置后, IsBusy 在视图模型假),焦点将设置为 NameTextBox 。如果一切正常,其他人可以适当地在自己的ViewModels使用 EnhancedBusyIndi​​cator ,只是绑定到不同的控制并启用的重点,假设他们的观点有一个intial BusyIndi​​cator控件有效

So the idea is when IsRemoteFocusEnabled is set to true in my ViewModel (which I do after I've set IsBusy to false in the ViewModel), focus will be set to NameTextBox. And if it works, others could use the EnhancedBusyIndicator and just bind to a different control and enable the focus appropriately in their own ViewModels, assuming their views have an intial BusyIndicator active.

不过,我得到视图时加载此异常:

However, I get this exception when the view is loaded:

设置属性foo.Controls.EnhancedBusyIndi​​cator.ControlToFocusOn引发了异常。 [行:45职位:26]

将这个解决方案,我试图工作的?如果是这样,什么是错的我有什么迄今(不能设置 ControlToFocusOn 属性)?

Will this solution I am attempting work? If so, what is wrong with what I have thus far (cannot set the ControlToFocusOn property)?

更新1

我安装了Visual Studio中的Silverlight 5 10工具,并得到了更好的错误消息航行时新的观点。现在我格特此错误消息:

I installed Visual Studio 10 Tools for Silverlight 5 and got a better error message when navigating to the new view. Now I gete this error message:

System.ArgumentException:类型System.Windows.Data.Binding的对象不能转换为类型System.Windows.Controls.UserControl

"System.ArgumentException: Object of type System.Windows.Data.Binding cannot be converted to type System.Windows.Controls.UserControl"

另外,我觉得我需要改变的DataContext此控件。在代码隐藏构造,DataContext设置为我的视图模型。我尝试添加一个DataContext属性添加到 EnhancedBusyIndi​​cator ,但没有工作:

Also, I think I need to change the DataContext for this control. In the code-behind constructor, DataContext is set to my ViewModel. I tried adding a DataContext property to the EnhancedBusyIndicator, but that did not work:

<my:EnhancedBusyIndicator
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    RemoteFocusIsEnabled="{Binding IsRemoteFocusEnabled}"
    IsBusy="{Binding IsDetailsBusyIndicatorActive}"
...
>






更新2

我需要改变用户控件控制因为我将被希望将焦点设置到文本框对象(执行控制)。但是,这并没有解决这个问题。

I need to change UserControl to Control since I will be wanting to set focus to TextBox objects (which implement Control). However, this does not solve the issue.

推荐答案

如果没有 BusyIndi​​cator控件在视图中,要解决的重点问题,常见的解决方法是添加代码

Without a BusyIndicator present in the view, the common solution to solve the focus problem is to add the code

Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });



到视图的加载事件。这实际上即使有 BusyIndi​​cator控件目前工程;但是, BusyIndi​​cator控件立即采取从Silverlight控件的其余部分集中了。解决的办法是调用后 BusyIndi​​cator控件不可以焦点()方法>忙

to the Loaded event of the view. This actually works even with the BusyIndicator present; however, the BusyIndicator immediately takes focus away from the rest of the Silverlight controls. The solution is to invoke the Focus() method of the control after the BusyIndicator is not busy.

我能够通过控制这样解决这个问题:

I was able to solve it by making a control like this:

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;
        }
    }
}

要使用它,更换 BusyIndi​​cator控件标签与新的 EnhancedBusyIndi​​cator 并添加适当的命名空间的XAML。

To use it, replace the BusyIndicator tags in your xaml with the new EnhancedBusyIndicator and add the appropriate namespace.

添加一个新的属性, ControlToFocusOn 元素中,并将其绑定到现有元素要专注才能在以后的<$视图C $ C> EnhancedBusyIndi​​cator 消失:

Add a new property, ControlToFocusOn inside the element, and bind it to an existing element in the view that you want focus to be on after the EnhancedBusyIndicator disappears:

<my:EnhancedBusyIndicator
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    ...
>
    ...
</my:EnhancedBusyIndicator>

在这种情况下,我专注于一个名为文本框 NameTextBox

In this case, I focused to a textbox called NameTextBox.

这就是它。这种控制会得到关注我们每次浏览网页的时间。虽然我们在页面上,如果 EnhancedBusyIndi​​cator 变得忙,不忙agiain,重点将不会去控制;这只是发生在初始加载。

That's it. This control will get focus every time we navigate to the page. While we are on the page, if the EnhancedBusyIndicator becomes busy and not busy agiain, focus will not go to the control; this only happens on initial load.

如果你想允许 EnhancedBusyIndi​​cator 来聚焦到 ControlToFocusOn 另一个时间,添加其他的财产, AllowedToFocus

If you want to allow the EnhancedBusyIndicator to focus to the ControlToFocusOn another time, add another property, AllowedToFocus:

<my:EnhancedBusyIndicator
    ControlToFocusOn="{Binding ElementName=NameTextBox}"
    AllowedToFocus="{Binding IsAllowedToFocus}"
    ...
>
    ...
</my:EnhancedBusyIndicator>

AllowedToFocus 设置为true,则下一次 EnhancedBusyIndi​​cator 从忙不忙,重点将转到 ControlToFocusOn 切换。

When AllowedToFocus is set to true, the next time EnhancedBusyIndicator switches from busy to not busy, focus will go to ControlToFocusOn.

AllowedToFocus也可以加载视图时,可以防止将焦点去控制设置为false。如果您绑定 AllowedToFocus 来一个ViewModel属性,您可能需要更改 BindingMode 。默认情况下,它是一次性

AllowedToFocus can also be set to false when loading the view, to prevent focus from going to a control. If you bind AllowedToFocus to a ViewModel property, you may need to change the BindingMode. By default, it is OneTime.

这篇关于绑定用户控件到自定义BusyIndi​​cator控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆