无法绑定到自己的依赖项属性

时间:2012-05-03 19:08:51

标签: .net silverlight binding silverlight-4.0 dependency-properties

我有一个Downloader,它有一个progress属性,它是:

    public static readonly DependencyProperty ProgressProperty = DependencyProperty.Register("Progress", typeof(int), typeof(Downloader), new PropertyMetadata(0, new PropertyChangedCallback(OnProgressChange)));

    public int Progress
    {
        get { return (int)this.GetValue(ProgressProperty); }
        private set { this.SetValue(ProgressProperty, value); }
    }

    private static void OnProgressChange(DependencyObject @object, DependencyPropertyChangedEventArgs e)
    {
        Downloader d = @object as Downloader;
        if (d.PropertyChanged != null) d.PropertyChanged(d, new PropertyChangedEventArgs("Progress"));
    }

当我尝试在其他类xaml中使用它时(m_downloader是Downloader类型的私有字段):

<sdk:Label Height="24" HorizontalAlignment="Left" Margin="360,12,0,0" Name="ProgressLabel" VerticalAlignment="Top" Width="38" Content="{Binding Path=m_downloader.Progress, StringFormat='\{0\} %'}" />
没有任何反应。在调试期间,我可以看到d.PropertyChanged始终为null。如何使其在标签中显示进度?

编辑1:

m_downloader的工作原理如下(临时更改为属性后):

public partial class AudioPlayer : UserControl
{
    public AudioPlayer()
    {
        m_downloader = new Downloader();
        InitializeComponent();
    }
    ...
    public Downloader m_downloader {get; private set;}
}

编辑2:

我在Blend中完成了绑定,它将xaml更改为:

<UserControl x:Name="audioPlayer" x:Class="Media.Controls.AudioPlayer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="125" d:DesignWidth="410" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

<Grid x:Name="LayoutRoot" Background="White">
    ...
    <sdk:Label Height="24" HorizontalAlignment="Left" Margin="337,12,0,0" Name="ProgressLabel" VerticalAlignment="Top" Width="61" Content="{Binding m_downloader.Progress, ElementName=audioPlayer, Mode=OneWay}" />
    ...
</Grid>
</UserControl>

为什么将ElementName设置为嵌套的名称,而不是嵌套的名称?这对我来说没有意义......但是在这种变化之后它正在发挥作用。

1 个答案:

答案 0 :(得分:1)

由于您正在解释之后,绑定机制的工作方式如下:

  1. 绑定机制取决于两件事:绑定上的路径和源

  2. 您的案例中的路径是“m_Downloader.Progress”,如果未明确设置源,则绑定将回退到使用标签上的DataContext

  3. 如果标签上没有设置DataContext,它将搜索DataContext 视觉树。

  4. 您可以使用{Binding Source = ...}或{Binding ElementName = ...}

  5. 明确设置来源

    例如,以下内容不起作用:

    <sdk:Label 
       x:Name="ProgressLabel"
       Content="{Binding Path=Progress}" />
    

    这是因为没有源,并且没有设置DataContext。

    您可以使用以下代码在代码中进行设置:

    ProgressLabel.DataContext = m_Downloader
    

    或者,您可能希望相对于嵌套对象进行绑定。

    <sdk:Label
       Content="{Binding m_Downloader.Progress}" />
    

    但是,这不会起作用

    1. m_Downloader不公开,

    2. m_Downloader甚至不是属性

    3. 未设置DataContext。

    4. 要解决此问题,请使用以下命令:

      public Downloader Downloader {get;设置; |

      public void InitializeComponent()   {      // ...

       // set DataContext to nesting object
       ProgressLabel.DataContext = this; 
      

      }

      如果您不想在代码中设置DataContext,则可以显式设置源。由于AudioPlayer有一个元素名称

      <UserControl x:Name="AudioPlayer" ... />
      

      您可以在绑定中引用它

      <sdk:Label
         Content="{Binding m_Downloader.Progress, ElementName=AudioPlayer}" />
      

      最后,您还可以通过将AudioPlayer上的DataContext设置为自身来完成此操作。

      <UserControl
         DataContext="{Binding RelativeSource={RelativeSource Self}}" />
      
      <sdk:Label
         Content="{Binding m_Downloader.Progress}" />