WinRT XAML数据绑定



我有以下场景:

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中并不存在。)

最新更新