0

У меня есть Downloader, которая имеет свойство прогрессировать, что:не может связываться с владельцем свойства зависимостей

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. Как заставить его работать, чтобы показать прогресс в ярлыке?

EDIT 1:

m_downloader как это работает (после того, как временное изменение собственности):

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

EDIT 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. Механизм связывания зависит от двух вещей: Пути и Источника на Binding

  2. Путь в вашей case, является «m_Downloader.Progress», и если источник не установлен явно, привязка возвращается к использованию DataContext на метке

  3. Если на этикетке нет набора данных, он ищет для DataCont ext до визуального дерева.

  4. Вы можете установить источник явно с помощью {Binding Source = ...} или {Binding 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 не установлен ,

Чтобы решить эту проблему, используйте следующую команду:

общественности Downloader Downloader {получить; набор; |

общественный недействительный InitializeComponent() { // ...

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

}

Если вы не хотите, чтобы установить DataContext в коде, вы можете установить источник в явном виде. Поскольку AudioPlayer имеет имя элемента

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

Вы можете ссылаться на него в вашем связывании

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

Наконец, вы также можете сделать это, установив DataContext на AudioPlayer себе.

<UserControl 
    DataContext="{Binding RelativeSource={RelativeSource Self}}" /> 

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

спасибо за точное объяснение +1, конечно;) – deha