【问题标题】:Get parent DataContext from inside ListView item从 ListView 项中获取父 DataContext
【发布时间】:2015-04-04 02:28:02
【问题描述】:

我的场景: 在当前页面中,我设置了一个DataContext,它包含两个属性,第一个(页面标题)Question,第二个(项目列表)Replies。

我将Replies 绑定到ListView 的ItemsSource 属性:

<ListView x:Name="responseList" ItemsSource="{Binding replies}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <local:CustomControl />
            </DataTemplate>
        </ListView.ItemTemplate>       
    </ListView>

到目前为止,没有任何问题。在Custom Control 内部,我还需要检索Question 元素的一些属性(在ListView 之外),将这些属性绑定到CustomControl 的XAML 中。 p>

我查看了这个,但没有运气,因为在 WinRT 中无法识别 FindAncestor: WPF Databinding: How do I access the "parent" data context?

另一个没有返回 DataContext: How to access Parent's DataContext in Window 8 store apps

<UserControl ....>
    <Grid Background="#33FFFFFF">
         <Grid.Resources>
              <local:converter1 x:Key="key" Question="{Binding Tag.Question, ElementName=responseList}"/>
         </Grid.Resources>
    </Grid>
</UserControl>

【问题讨论】:

  • ElementName 解决方案仅在您与所引用的命名元素处于相同命名上下文中时才能工作,这在 DataTemplates 中工作正常。您正在从用户控件内部尝试,这是一个不同的命名上下文。我认为目前没有解决方案可以仅通过 Xaml 和 Binding 执行此操作。您可能必须在回复中添加父导航属性。
  • 这正是 Bart van Nierop 刚刚提出的答案。 :)

标签: c# listview binding windows-phone-8.1 winrt-xaml


【解决方案1】:

您可以让您的Replies 对他们要回复的问题有一个(n 不可变的)引用。或者,也许更好,假设你的DataContext 是SomePageViewModel,让它的replies 列表不是你的域模型Reply,而是一个知道回复和相关部分的ReplyViewModel问题。

这实际上并不能回答您的问题,但设计要好得多,而且它确实解决了问题。

在不改变您的Reply 域模型的情况下可以构建的一种方法如下:

// Domain Model example
class Question
{
    public String Text { get; set; }
    public String Author { get; set; 
    public IEnumerable<Reply> Replies { get; set; }
}

// Domain Model example
class Reply
{
    public String Author { get; set; }  
    public String Text { get; set; }
}

// DataContext example
class WhatYouUseAsDataContext
{
    public Question Question { get; set; } 

    // Your replies -- this is what your ListView binds to.
    public IEnumerable<ReplyViewModel> Replies { get; set; } 

    public WhatYouUseAsDataContext()
    {
        Question = SomeWayToGetTheQuestion();
        Replies = Question.Replies.Select(reply => new ReplyViewModel()
        {
            Reply = reply,
            QuestionAuthor = Question.Author
        });
    }
}

// Newly introduced viewmodel class
class ReplyViewModel
{
    public Reply Reply { get; set; }
    public String QuestionAuthor { get; set; }
}

【讨论】:

  • 这只能修改Reply对象结构吗?我想不出一种方法来构建功能性 ViewModel
  • 我希望找到一种不会有重复属性的方法,但似乎不可能。另一种方法是对当前打开的问题使用全局变量...
  • 从我发现这确实是不可能的(不改变你的模型),但这不是一件坏事。一方面,它使您的用户控件可以轻松地在应用程序的其他部分重用,因为它不依赖于其父级的父级DataContext,并且它使您可以更清晰地分离业务逻辑和表示。
  • 另一方面,这意味着传递的数据要多得多,而且由于回复列表最多可以计算 90 条,因此它可能会更重
  • 如果您以这种方式复制了许多值对象,您可能需要考虑将Question 本身添加到ReplyViewModel,而不是其内容。对某个对象的 90 次引用确实不会对性能产生明显影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
相关资源
最近更新 更多