2

我有一个需要外部有状态模块才能工作的 ValueConverter。所以我从 Freezable 继承了它并声明了依赖属性。

public class Decorator : Freezable, IValueConverter
{
  public static readonly DependencyProperty HighlighterProperty =
      DependencyProperty.Register("Highlighter", typeof (IHighlighter), typeof (Decorator), new PropertyMetadata(null));

  public ITypeNameHighlighter TypeNameHighlighter
  {
    get { return (ITypeNameHighlighter)GetValue(TypeNameHighlighterProperty); }
    set { SetValue(TypeNameHighlighterProperty, value); }
  }
  //...
}

然后我使用 DataTemplate 和 DataTemplateSelector 来显示一个视图。在资源中创建一个Decorator实例并在绑定中使用

<DataTemplate x:Key="ViewTemplate">
...

<ListView ...>
  <Control.Resources>
    <GUI:Decorator x:Key="Decorator" **Highlighter="{Binding Highlighter}"** />
  </Control.Resources>
...

<GridViewColumn>
  <GridViewColumnHeader  ... />

    <GridViewColumn.CellTemplate>
      <DataTemplate>
        <GUI:RichTextBlock RichText="{Binding Path=Title, Converter={**StaticResource Decorator**}}" />
      </DataTemplate>
  </GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView>
...
</DataTemplate>

问题是当创建多个 View 实例时,它们都使用一个(第一个)Decorator 实例将实体转换为 RichText(而实际上创建了几个 Decorator 实例 - 一个按视图)。Highlighter 有一个状态,这就是为什么每个 View 都必须使用自己的 Decorator 实例的原因。

任何评论为什么会有这种行为?任何想法如何解决它?

更新: DJ 问我“为什么需要多个转换器实例”,所以我将描述该任务。

应用程序中有多个相同视图的实例。每个视图都包含自己的文本过滤器,用于从 ListView 中过滤掉元素。ViewModel 端有一个 Highlighter,它有一个过滤器文本和字符串(在我们的例子中是 ListView 元素标题)作为输入,并返回标题的哪些部分与过滤器文本匹配的信息。Decorator converts 具有从 Highlighter 返回的标题和信息作为输入,RichText 作为输出。

我同意 WPF 提供的表单中的 ValueConverter 不是很适合这个问题。但我在 View 方面看不到任何其他优雅的方式。

爱德华

4

1 回答 1

0

将 x:Shared=False 放在声明转换器资源的位置。在每次调用时,它都会为您提供新对象。

<GUI:Decorator x:Shared=False x:Key="Decorator" **Highlighter="{Binding Highlighter}"** /> 
于 2012-09-17T09:10:47.270 回答