WPF绑定找不到引用

时间:2015-10-14 05:07:12

标签: c# wpf xaml data-binding

我一直关注此answer以公开我的用户控件的一些属性。

问题在于绑定没有找到来源,我不明白如何正确地做到这一点。

XAML:

<UserControl x:Class="Project.UI.Views.ucFilterDataGrid"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Project.UI.Views"
         xmlns:watermark="clr-namespace:Project.UI.Watermark"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Margin" Value="0,0,00,30"/>
        </Style>
    </StackPanel.Resources>
    <AdornerDecorator>
        <TextBox Name="SearchTextBox">
            <watermark:WatermarkService.Watermark>
                <TextBlock Name="waterMarkText" 
                           Text="{Binding Path=WatermarkContent, 
                                  RelativeSource={RelativeSource FindAncestor,
                                  AncestorType=local:ucFilterDataGrid}}"
                           HorizontalAlignment="Center" >

                </TextBlock>
            </watermark:WatermarkService.Watermark>
        </TextBox>
    </AdornerDecorator>

    <DataGrid Name="Results">

    </DataGrid>
</StackPanel>

CS:

namespace Project.UI.Views
{
/// <summary>
/// Interaction logic for ucFilterDataGrid.xaml
/// </summary>
public partial class ucFilterDataGrid : UserControl
{
    public ucFilterDataGrid()
    {
        InitializeComponent();
    }


    public string WatermarkContent
    {
        get { return GetValue(WatermarkContentProperty).ToString(); }
        set { SetValue(WatermarkContentProperty, value); }
    }

    public static readonly DependencyProperty WatermarkContentProperty = DependencyProperty.Register("WatermarkContent", typeof(string), typeof(ucFilterDataGrid), new FrameworkPropertyMetadata(string.Empty));
}
}

窗口:

<Grid>
    <local:ucFilterDataGrid Margin="301,34,31,287" WatermarkContent="MyTest"/>
</Grid>

结果将是一个空白的TextBlock。如果我只是从我的水印UserControl中删除它并将其放在与DataGrid相同的级别上,它将起作用。

2 个答案:

答案 0 :(得分:6)

这里的问题是你的TextBlock被设置为附加属性的值,这里是:

<watermark:WatermarkService.Watermark>
            <TextBlock ...>
            </TextBlock>
</watermark:WatermarkService.Watermark>

watermark:WatermarkService.Watermark是附属财产。它的值只是内存中的一个对象,与视觉树分离。因此,您无法使用RelativeSourceElementName绑定。您需要一些代理来桥接断开连接。 Source将用于绑定,您应该尝试的代码如下:

<TextBox Name="SearchTextBox">
        <TextBox.Resources>
            <DiscreteObjectKeyFrame x:Key="proxy" 
                                    Value="{Binding Path=WatermarkContent, 
                                            RelativeSource={RelativeSource FindAncestor,
                                            AncestorType=local:ucFilterDataGrid}}"/>
        </TextBox.Resources>
        <watermark:WatermarkService.Watermark>
            <TextBlock Name="waterMarkText" 
                       Text="{Binding Value, Source={StaticResource proxy}}"
                       HorizontalAlignment="Center" >

            </TextBlock>
        </watermark:WatermarkService.Watermark>
</TextBox>

答案 1 :(得分:1)

前几天我做了类似的事,如果我没记错的话。您必须从INotifyPropertyChanged接口派生,并告知组件更新WatermarkContent时属性已更改。否则,xaml(view)将不知道何时更改Text,并且绑定不会更新。

以下是您可以尝试的内容

using System.ComponentModel;

public partial class ucFilterDataGrid : UserControl, INotifyPropertyChanged
{
    public static readonly DependencyProperty WatermarkContentProperty = DependencyProperty.Register("WatermarkContent", typeof(string), typeof(ucFilterDataGrid), new FrameworkPropertyMetadata(string.Empty));
    public event PropertyChangedEventHandler PropertyChanged;

    public ucFilterDataGrid()
    {
        InitializeComponent();
    }

    public string WatermarkContent
    {
        get { GetValue(WatermarkContentProperty).ToString(); }
        set { 
             SetValue(WatermarkContentProperty, value); 
             RaisePropertyChanged();
        }
    }

    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

我添加了INotifyPropertyChanged并在每次更改WatermarkContent时引发事件。

希望它有所帮助!