0

我有一個下載器,它有一個進度屬性,它是:不能綁定到自己的依賴屬性

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是下載的私人領域類型):

<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始終爲空。如何使它在標籤中顯示進度?

編輯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設置爲名稱嵌套,而不是嵌套的?這對我來說沒有意義......但是它在這個變化之後起作用。

+0

如果m_downloader是私人的,你不能綁定到它。它需要公開。 –

+0

我改爲公開,但仍然沒有運氣...... – deha

+0

你確定,DataContext設置正確,所以你可以綁定到m_downloader? – Euphoric

回答

1

既然你是一個解釋後,該約束機制的工作原理很喜歡這樣的:

  1. 的結合機制取決於兩件事情:路徑和源在綁定

  2. 的路徑你大小寫是「m_Downloader.Progress」,並且如果未明確設置源,則綁定返回使用標籤上的DataContext

  3. 如果標籤上沒有設置DataContext,它將搜索爲DataCont分機 了視覺樹。

  4. 您可以明確地設置源使用{綁定源= ...}或{綁定的ElementName = ...}

例如,以下將不起作用:

<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未設置。

要解決此問題,使用以下命令:

公衆下載器下載{獲得;設置; |

公共無效的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}" /> 
+0

感謝您的確切解釋+1);當然;) – deha