我有一个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设置为嵌套的名称,而不是嵌套的名称?这对我来说没有意义......但是在这种变化之后它正在发挥作用。
答案 0 :(得分:1)
由于您正在解释之后,绑定机制的工作方式如下:
绑定机制取决于两件事:绑定上的路径和源
您的案例中的路径是“m_Downloader.Progress”,如果未明确设置源,则绑定将回退到使用标签上的DataContext
如果标签上没有设置DataContext,它将搜索DataContext 视觉树。
您可以使用{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}" />
但是,这不会起作用
m_Downloader不公开,
m_Downloader甚至不是属性
未设置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}" />