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が常に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がネストされた名前ではなく、ネストされた名前に設定されているのはなぜですか?私には意味がありません...しかし、この変更後は機能しています。

4

1 に答える 1

1

説明が必要なため、バインディングメカニズムは次のように機能します。

  1. バインディングメカニズムは、バインディングのパスとソースの2つに依存します。

  2. あなたの場合のパスは「m_Downloader.Progress」であり、ソースが明示的に設定されていない場合、バインディングはラベルのDataContextの使用にフォールバックします

  3. ラベルにDataContextが設定されていない場合は、ビジュアルツリーの上位でDataContextを検索します。

  4. {Binding Source=...}または{BindingElementName=...}を使用してソースを明示的に設定できます

たとえば、次は機能しません。

<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が設定されていません。

これを解決するには、以下を使用します。

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}" />
于 2012-05-03T22:15:19.230 に答える