我有以下场景:
public class HubModel
{
public string Name { get; set; }
}
我在ViewModel中创建了一个ObservableCollection,并将HubPage上的DataContext设置为该ViewModel。
在HubPage上,我有一个名为TestUserControl的简单UserControl。
来自UserControl:的XAML
<UserControl
x:Name="userControl"
....>
<Grid>
<StackPanel Orientation="Vertical">
<ItemsControl x:Name="ItemsContainer" ItemsSource="{Binding Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Margin="0,0,0,20">
<StackPanel>
<TextBlock Foreground="Black" HorizontalAlignment="Left" FontFamily="Arial" FontSize="42" VerticalAlignment="Center" Name="CurrencyTextBlock" Text="{Binding Path=Text,ElementName=userControl}"></TextBlock>
</StackPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
用户控制代码背后:
public ObservableCollection<object> Collection
{
get { return (ObservableCollection<object>)GetValue(CollectionProperty); }
set { SetValue(CollectionProperty, value); }
}
public static readonly DependencyProperty CollectionProperty =
DependencyProperty.Register("Collection", typeof(ObservableCollection<object>), typeof(TestUserControl), new PropertyMetadata(null));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(TestUserControl), new PropertyMetadata(string.Empty));
因为我的UserControl不应该知道HubModel,所以我想通过DependencyProperty绑定TextBlock文本路径。
来自HubPage:的XAML
...
<userControls:TestUserControl Collection="{Binding TestCollection}" Text="Name"/>
...
Collection="{Binding-TestCollection}"将列表设置为我的UserControl中的DependencyProperty。
Text="Name"设置属性名称。计划是,我的UserControl在DependencyProperty中查找TextBlock文本"Name",并从绑定类HubModel的属性"Name"中获取值。
问题是,我的UserControl在DependencyProperty中找到"Name",并为集合中的每个条目显示"Name"而不是类中的属性值。
这样的事情可能发生吗?或者在UserControls中绑定的最佳方式是什么。在我的选项中,不应该知道绑定类中的属性名称。
谢谢Daniel
这里棘手的部分是,您实际上是在尝试绑定Binding
本身(即Binding.Path
)的属性。这是不可能的,因为Binding
不是DependencyObject,Binding.Path
也不是依赖属性。所以你必须退一步,找到另一种方法。
一种方法是创建TextBlock
的子类,添加依赖属性SourceObject
(对于对象,在本例中为"HubModel")和PropertyName
(对于要显示的属性,为"Name")或类似属性。这将允许您通过使用反射来更新Text
。
所以你应该写这个而不是TextBlock
:
<my:ExtendedTextBlock SourceObject="{Binding}" PropertyName="{Binding Path=Text,ElementName=userControl}" />
ExtendedTextBlock
看起来像这样:
public class ExtendedTextBlock : TextBlock
{
public object SourceObject
{
get { return GetValue(SourceObjectProperty); }
set { SetValue(SourceObjectProperty, value); }
}
public static readonly DependencyProperty SourceObjectProperty =
DependencyProperty.Register("SourceObject",
typeof(object),
typeof(ExtendedTextBlock),
new PropertyMetadata(UpdateText)
);
public string PropertyName
{
get { return GetValue(PropertyNameProperty); }
set { SetValue(PropertyNameProperty, value); }
}
public static readonly DependencyProperty PropertyNameProperty =
DependencyProperty.Register("PropertyName",
typeof(string),
typeof(ExtendedTextBlock),
new PropertyMetadata(UpdateText)
);
public static void UpdateText(object sender, DependencyPropertyChangedEventArgs args)
{
var owner = (ExtendedTextBlock)sender;
if (owner.SourceObject == null || string.IsNullOrEmpty(owner.PropertyName))
return;
var prop = SourceObject.GetType().GetProperty(PropertyName);
if (prop == null)
return;
var val = prop.GetValue(SourceObject, null);
owner.Text = (val == null ? "" : val.ToString());
}
}
(在WPF中,你可以使用MultiBinding,但据我所知,这在WinRT中并不存在。)