如何将DataTemplate项绑定到导航属性中的单个实体

时间:2015-04-30 09:07:18

标签: wpf entity-framework

我正在开发一个管理文章的知识库应用程序。

文章由标题(Id,作者等)和一组文本片段组成,其中一个包含标题(TextType == 2)。

有一个列表框用于显示Id和Title,但我无法正确地将标题绑定到文本块。

我在其他地方有工作代码来加载标题实体

ArticleText te =  _header.ArticleTexts.Where(at => at.TextType == 2).FirstOrDefault();

因此产生标题的实体的属性为te.Body

我在代码

中设置了列表框的ItemsSource
public ObservableCollection<ArticleHeader> HeaderCollection
{
    get
    {
        return (ObservableCollection<ArticleHeader>)articlesListBox.ItemsSource;
    }
    set
    {
        articlesListBox.ItemsSource = value;
    }
}

正确显示Id,但似乎无法找到绑定到(延迟加载的)标题字符串的方法。

我的(简化)xaml如下

        <ListBox Name="articlesListBox">
            <ListBox.ItemTemplate>
                <DataTemplate> 
                    <DockPanel>
                        <TextBlock DockPanel.Dock="Left" Text="{Binding Path=Id}"/>
                        <TextBlock TextWrapping="WrapWithOverflow" Margin="0,0,2,0"/>
                    </DockPanel> 
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

我知道可能有很多解决方案,但下一步是什么?

3 个答案:

答案 0 :(得分:0)

与ID相同吗?

<TextBlock Text={Binding Path=Body}/>

<TextBlock Text={Binding Path=Body.Title} />

可能误解了你的问题......

答案 1 :(得分:0)

ArticleTexts.Where(TextType==2)

部分应该在viewmodel / controller中发生,而不是在XAML中发生。

您可以创建一个新的匿名对象集合,只保存您需要的信息(id和title),将其作为属性公开并将ListBox绑定到该集合,而不是将ListBox绑定到ArticleHeader对象的集合。

修改

总是可以选择使用BindingConverter,但这需要创建一个全新的类,这比创建一个新的集合更麻烦。也许您应该在问题中添加您想到的解决方案,并明确询问是否存在更好的替代方案。

答案 2 :(得分:0)

我不禁想到必须有其他(更好)的方法,但我能够通过定义一个值转换器来实现我的要求。

 [ValueConversion(typeof(ArticleHeader), typeof(String))]
    public class HeaderToTitleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            ArticleHeader ah = value as ArticleHeader;

            ArticleText textEntity = null;

            using (KnowledgeManagementEntities ctx = KBContext.NewContext())
            {
                ctx.ArticleHeaders.Attach(ah);
                textEntity = ah.ArticleTexts.Where(at => at.TextType == KBConstants.TITLE_TYPE).FirstOrDefault();
            }

            if (textEntity == null)
                return "";

            if (String.IsNullOrEmpty(textEntity.Body))
                return "";

            return textEntity.Body;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

然后在App.Xaml

<Application x:Class="SupportKB.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             xmlns:local="clr-namespace:SupportKB" xmlns:Properties="clr-namespace:SupportKB.Properties">
    <Application.Resources>
        <ResourceDictionary> 
            <local:HeaderToTitleConverter x:Key="headerToTitleConverter" /> 
        </ResourceDictionary>
    </Application.Resources>
</Application>

所以xaml现在看起来像这个

<DataTemplate>
    <DockPanel Margin="0,2"> 
        <TextBlock DockPanel.Dock="Left" Text="{Binding Path=Id}" Width="50" />
        <TextBlock TextWrapping="WrapWithOverflow" 
                   Margin="0,0,2,0" 
                   Text="{Binding Converter={StaticResource headerToTitleConverter}}"/> 
    </DockPanel>
</DataTemplate>

最后,我将重新设计,以便标题列表为主,并从中选择标题。