【问题标题】:Update when binding has no path绑定没有路径时更新
【发布时间】:2016-06-02 13:50:13
【问题描述】:

我有以下几点:

<DataTemplate DataType="{x:Type vm:MyViewModel}">
  <Grid>
    ...
    <ContentControl Content="{Binding}"
                    ContentTemplateSelector="{StaticResource MySelector}"/>
    ...
  </Grid>
</DataTemplate>

其中MySelector 给出MyViewModel 的不同视图,如MyViewModel.ViewName 所示,并且

class MyViewModel : INotifyPropertyChanged
{
    ...
    public string ViewName
    {
        get { return _viewName; }
        set
        {
            _viewName = value;
            OnPropertyChanged(() => ViewName);
        }
    }
    ...
}

如何在ViewName 更改时更新内容控件中的绑定?

注意我还尝试在 MyViewModel 上创建一个属性,该属性仅返回自身,绑定到该属性,然后每当 ViewName 更改时为该属性引发 PropertyChanged

<DataTemplate DataType="{x:Type vm:MyViewModel}">
  <Grid>
    ...
    <ContentControl Content="{Binding This}"
                    ContentTemplateSelector="{StaticResource MySelector}"/>
    ...
  </Grid>
</DataTemplate>

class MyViewModel : INotifyPropertyChanged
{
    ...
    public string ViewName
    {
        get { return _viewName; }
        set
        {
            _viewName = value;
            OnPropertyChanged(() => ViewName);
            OnPropertyChanged(() => This);
        }
    }
    public MyViewModel This { get { return this; } }
    ...
}

但是当ViewName 在任何一种情况下发生变化时,我的模板选择器都不会被调用。

【问题讨论】:

  • 有点麻烦,但可能有用:使用MultiBinding。这需要一个多值转换器,因此编写一个只从 Convert 中返回 values[0] 的存根多值转换器。然后您可以使用绑定填充您的多个MultiBinding:首先是无路径绑定,然后是绑定到您希望触发更新的任何属性。当他们提出 PropertyChanged 时,框架会愉快地调用您的转换器。我想测试一下,如果 Convert 的返回值永远不会改变,是否会再次调用模板选择器,这是唯一的事情。
  • @EdPlunkett,不。仍然没有调用选择器。
  • 我建议使用DataTrigger 来更改您的ContentTemplate,而不是使用ContentTemplateSelector,例如this。众所周知,ContentTemplateSelector 的最大限制之一是它们仅在 .Content 属性更改时重新评估,因此在您的情况下,您必须将 .Content 绑定到 ViewName 才能重新-评估要使用的模板。我猜你的第二段代码不起作用,因为This 从未真正改变过,并且是对象的相同引用。
  • 糟糕,我使用了错误的链接作为使用 DataTrigger 更改 ContentTemplate 的示例...我的意思是 this one
  • 我不会再浪费时间在我的想法上——我试试 Rachel 的吧。

标签: wpf data-binding


【解决方案1】:

所以看起来 Rachel 引导我找到了正确的答案(或者至少是可行的)。

感觉有点hacky,但它确实有效。我继承了ContentControl 并覆盖了OnContentChanged() 方法以在内容更改时显式地重新调用模板选择器。

public class DynamicTemplatedContentControl : ContentControl
{
    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        if (ContentTemplateSelector == null) return;

        ContentTemplate = ContentTemplateSelector.SelectTemplate(newContent, this);
    }
}

然后在我的 XAML 中,我只使用第二种方法(在上面的问题中)创建一个 This 属性,我将我的内容绑定到该属性。

【讨论】:

  • 在最坏的情况下,这对我来说似乎有点骇人听闻。我喜欢它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-04
  • 2011-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多