简体   繁体   English

具有自定义依赖项属性的UserControl问题

[英]Problem with UserControl with custom Dependency Property

I'm writing a user control with a dependency property for a search text called SearchText. 我正在为名为SearchText的搜索文本编写一个具有依赖项属性的用户控件。 It is a dependency property because I want to allow consumers of the control to use data binding. 这是一个依赖项属性,因为我想允许控件的使用者使用数据绑定。 The user control contains a WPF TextBox where the user can enter the search text. 用户控件包含一个WPF文本框,用户可以在其中输入搜索文本。

I could use data binding to connect the SearchText dependency property of the user control with the Text dependency property of the TextBox, but this binding only fires when the text box looses input focus. 我可以使用数据绑定将用户控件的SearchText依赖项属性与TextBox的Text依赖项属性连接起来,但是仅当文本框失去输入焦点时才会触发此绑定。 What I want is SearchText to be updated after every change of Text. 我想要的是SearchText在每次更改文本后都进行更新。 So I have added a TextChanged event handler to the user control where I set SearchText to the value of Text. 因此,我在用户控件中添加了TextChanged事件处理程序,在其中将SearchText设置为Text的值。

My Problem is, the SearchText binding doesn't work, the source never gets updated. 我的问题是,SearchText绑定不起作用,源代码永远不会更新。 What am I doing wrong? 我究竟做错了什么?

Here's the relevant part of the user controls code-behind: 下面是用户控件的相关部分:

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

The window that contains an instance of the user control has its DataContext set to an object that has a property also called SearchText. 包含用户控件实例的窗口将其DataContext设置为一个对象,该对象的属性也称为SearchText。

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

The data context of the Window: 窗口的数据上下文:

public class DataSourceUserManual : DataSourceBase
{
    private string _searchText;
    public string SearchText
    {
        get { return _searchText; }
        set
        {
            _searchText = value;
            ...
            OnPropertyChanged("SearchText");
        }
    }
}

Unfortunately, this setter is not called when I type into the text box. 不幸的是,当我在文本框中键入内容时,不会调用此setter。 Any ideas? 有任何想法吗?


After following Quartermeisters hint I've removed the TextBox_TextChanged event handler and installed a binding which keeps TextBox.Text and UserControl.SearchText in sync. 在遵循Quartermeisters提示之后,我删除了TextBox_TextChanged事件处理程序并安装了使TextBox.Text和UserControl.SearchText保持同步的绑定。

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

This binding seems to work. 这种绑定似乎有效。 But now the binding between the user control and the data context of the window is broken (the source is never updated). 但是现在,用户控件和窗口的数据上下文之间的绑定已断开(源永远不会更新)。 I've changed it a little bit 我改变了一点

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

but with no effect. 但没有效果。

Anything special I have to take care of regarding these "chained" bindings? 关于这些“链接”绑定,我有什么特别需要注意的吗?

You can force the TextBox to update the binding source every time Text changes by changing the UpdateSourceTrigger to PropertyChanged from the default of LostFocus: 您可以通过将UpdateSourceTrigger从默认的LostFocus更改为PropertyChanged,来强制TextBox每次文本更改时都更新绑定源:

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

See the MSDN article on Binding.UpdateSourceTrigger . 请参阅Binding.UpdateSourceTrigger上的MSDN文章。


On your updated question, it looks like the source property is not updating because you are doing a one-way binding. 在您更新的问题上,由于您正在执行单向绑定,因此似乎源属性未更新。 You can either make that binding two-way in XAML by specifying the Mode : 您可以通过指定Mode在XAML中进行双向绑定:

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

Or you can specify FrameworkPropertyMetadataOptions.BindsTwoWayByDefault in your dependency property, which is what TextBox.Text does: 或者,您可以在依赖项属性中指定FrameworkPropertyMetadataOptions.BindsTwoWayByDefault ,这是TextBox.Text的作用:

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

You need to specify the PropertyChangedCallback parameter for the UIPropertyMetadata constructor. 您需要为UIPropertyMetadata构造函数指定PropertyChangedCallback参数。

This CodeProject article does exactly what you want. 此CodeProject文章完全满足您的要求。 See How to Use Windows Vista Search API from a WPF Application at http://www.codeproject.com/KB/WPF/Vista_Search_in_WPF.aspx . 请参阅如何从一个WPF应用程序使用Windows Vista的搜索API http://www.codeproject.com/KB/WPF/Vista_Search_in_WPF.aspx

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM