使用自定义依赖属性的UserControl出现问题

5
我正在编写一个用户控件,其中包含一个名为SearchText的搜索文本依赖属性。这是一个依赖属性,因为我希望控件的使用者能够使用数据绑定。用户控件包含一个WPF TextBox,用户可以在其中输入搜索文本。
我可以使用数据绑定将用户控件的SearchText依赖属性与TextBox的Text依赖属性连接起来,但是此绑定仅在文本框失去输入焦点时触发。我想要的是每次更改Text后都更新SearchText。
因此,我在用户控件中添加了一个TextChanged事件处理程序,在其中将SearchText设置为Text的值。
我的问题是,SearchText绑定不起作用,源永远不会更新。我做错了什么?
以下是用户控件代码后台的相关部分:
public partial class UserControlSearchTextBox : UserControl
{
    public string SearchText
    {
        get { return (string)GetValue(SearchTextProperty); }
        set { SetValue(SearchTextProperty, value); }
    }

    public static readonly DependencyProperty SearchTextProperty =
        DependencyProperty.Register("SearchText", typeof(string), typeof(UserControlSearchTextBox), new UIPropertyMetadata(""));

    private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        SearchText = ((TextBox)sender).Text;
    }
    ...
}

包含用户控件实例的窗口其DataContext被设置为一个也称为SearchText的属性的对象。

<uc:UserControlSearchTextBox SearchText="{Binding SearchText}" />

窗口的数据上下文:
public class DataSourceUserManual : DataSourceBase
{
    private string _searchText;
    public string SearchText
    {
        get { return _searchText; }
        set
        {
            _searchText = value;
            ...
            OnPropertyChanged("SearchText");
        }
    }
}

很遗憾,当我输入文本框时,此setter不会被调用。有什么想法吗?


在按照Quartermeisters的提示后,我已经移除了TextBox_TextChanged事件处理程序,并安装了一个绑定来保持TextBox.Text和UserControl.SearchText同步。

<TextBox Text="{Binding ElementName=root, 
                        Path=SearchText, 
                        UpdateSourceTrigger=PropertyChanged}" />

这个绑定似乎起作用了。但是现在用户控件与窗口的数据上下文之间的绑定已经断开了(源永远不会更新)。我稍微改变了它

<uc:UserControlSearchTextBox SearchText="{Binding Source={StaticResource ResourceKey=dataSource}, 
                                                  Path=SearchText}" />

但是没有任何效果。

关于这些“链接”绑定,我需要特别注意什么吗?

2个回答

5

您可以通过将UpdateSourceTrigger更改为PropertyChanged来强制TextBox在每次文本更改时更新绑定源,而不是默认的LostFocus:

<TextBox Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />

请参阅MSDN文章Binding.UpdateSourceTrigger
在你更新的问题中,看起来源属性没有更新是因为你正在进行单向绑定。你可以通过在XAML中指定Mode来使该绑定变为双向绑定:
<uc:UserControlSearchTextBox SearchText="{Binding Source={StaticResource ResourceKey=dataSource}, 
                                              Mode=TwoWay,
                                              Path=SearchText}" />

或者您可以在依赖属性中指定FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,这就是TextBox.Text所做的:

public static readonly DependencyProperty SearchTextProperty =
    DependencyProperty.Register("SearchText", typeof(string), typeof(UserControlSearchTextBox), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

谢谢你的提示!但是现在我有两个绑定存在问题,请查看我的更新问题。 - Mathias Koch
我的两个绑定如果我将模式设置为OneWayToSource就可以工作了,所以现在所有问题都得到了解答。谢谢。 - Mathias Koch
之前没有注意到你更新的答案...现在我尝试设置FrameworkPropertyMetadataOptions.BindsTwoWayByDefault并将两个绑定都保持双向 - 它起作用了!再次感谢。 - Mathias Koch
因为我没有将默认绑定设置为TwoWay,所以我遇到了一个非常愚蠢的错误。感谢你的提示! - Sören

0

您需要为UIPropertyMetadata构造函数指定PropertyChangedCallback参数。

这篇CodeProject文章正好满足您的需求。请参阅http://www.codeproject.com/KB/WPF/Vista_Search_in_WPF.aspx中的如何从WPF应用程序使用Windows Vista搜索API

    ...
    new UIPropertyMetadata(
        default(string), 
        new PropertyChangedCallback(TextBox_TextChanged)
    )
    ...

    static void TextBox_TextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
        ...
    }

谢谢你的回答,但我认为这不是我需要的。也许你可以看一下我的更新问题。 - Mathias Koch
所有问题现在都已经回答了。谢谢。 - Mathias Koch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接