WPF绑定到用户控件自定义DependencyProperty

7

我有一个名为SongDescription的自定义用户控件:

<UserControl x:Class="DPTestAp.SongDescription" ...>
    <Grid x:Name="LayoutRoot">
        <DockPanel Height="50">
            <TextBlock x:Name="title" Text="{Binding name}" Width="100" Height="30"/>
            <TextBox x:Name="lyrics"/>
        </DockPanel>
    </Grid>
</UserControl>

我给它添加了一个DependencyProperty:

public partial class SongDescription : UserControl
{
    public static readonly DependencyProperty SongProperty = DependencyProperty.Register("Song", typeof(Song), typeof(SongDescription));

    public Song Song
    {
        get
        {
            return (Song)GetValue(SongProperty);
        }
        set
        {
            SetValue(SongProperty, value);
            updateLyrics()
        }
    }

    private void updateLyrics()
    {
        lyrics.Text = Song.lyrics;
    }

    public SongDescription()
    {
        InitializeComponent();
    }
}

问题是:如何将某些内容绑定到这个SongProperty上? 我在我的主窗口中使用SongDescription,就像这样:
<local:SongDescription x:Name="songDescription" Song="{Binding DataContext}"/>

我无法让我的文本框歌词显示歌词。在主窗口中,我尝试将DataContext设置为songDescription,如下所示:

songDescription.DataContext = new Song() { name="Home", lyrics="Hold on, to me as we go" };

或者像这样针对窗口本身进行操作:
DataContext = new Song() { name="Home", lyrics="Hold on, to me as we go" };

我尝试将Song作为资源并将其绑定到SongProperty,代码如下:

<Window.Resources>
    <local:Song x:Key="res" name="Home" lyrics="Hold on, to me as we go"/>
</Window.Resources>
<Grid>
    <local:SongDescription x:Name="songDescription" Song="{StaticResource res}"/>
</Grid>

没有任何帮助。TextBlock title 可以很好地绑定歌曲名称,但我无法调用 updateLyrics() 方法。(在实际应用中,这个方法更为复杂,因此我不能像处理名称那样使用绑定)。

谢谢!

2个回答

9
是的,这就是使用依赖属性时需要注意的问题。你绝对不能在访问器方法(get/set)中放置验证代码,因为WPF会将依赖属性存储在它自己管理的表格中。这就是为什么你必须注册依赖属性,它实际上为每个属性创建了一个条目以存储关联的值,并且当你使用'GetValue' / 'SetValue'时,你正在更新这个表格上的条目(顺便说一下,这与WPF如何管理数据绑定有关)。
然而,WPF可以(并且会)完全绕过您的属性访问器,因为它直接访问真实数据。如果它可以直接访问数据,为什么要使用您的访问器呢?相反,您需要实现一个“PropertyChanged”回调函数或一些WPF认可的验证方法,但永远不要在您的访问器中执行此操作
请参见:

http://msdn.microsoft.com/en-us/library/ms752914.aspx


但是,如果PropertyChanged回调是共享函数,我将无法更新任何控件! - Hamed Zakery Miab

2
除了sircodesalot的回答之外,您在歌词文本框上没有任何限制。另外,由于您绑定的歌曲是一个类,因此您需要完全指定要在框中显示的属性的路径,例如“Path = Song.Lyrics”。
还要考虑的一件事是,使用依赖属性时,默认情况下您的模式将是单向的,因此使文本字段可编辑实际上是无意义的,除非您更改它。
第三,如果您正在使用MVVM,您只需要将主窗口上下文设置为视图模型,并具有匹配的Song属性以进行绑定。

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