1

I need to modify one of the bound properties in my DataTemplate. The template is defined like this (relevant portion only):

<DataTemplate x:Key="MyImageTemplate">
  <Image>
    <Image.Source>
      <MultiBinding Converter="{StaticResource MyImageConverter}">
        <Binding Path="Source" />
        <Binding Path="TransparencyColor" />
        <Binding Path="TransparencyTolerance" />
      </MultiBinding>
    </Image.Source>
  </Image>
</DataTemplate>

Depending upon a condition, I need to change first binding from Source to another property Source2. Having spent the better part of the afternoon with this, I can't make the following simple code of my DataTemplateSelector work:

Public Class MyDataTemplateSelector
  Inherits DataTemplateSelector

  Public Overrides Function SelectTemplate(item As Object, container As DependencyObject) As DataTemplate
    Dim DT = DirectCast(Application.Current.FindResource("MyImageTemplate"), DataTemplate)
    Dim Control = DirectCast(DT.LoadContent(), FrameworkElement)

    Dim MB = BindingOperations.GetMultiBinding(item, System.Windows.Controls.Image.SourceProperty)
    Dim Source2Binding As New Binding(NameOf(ImageVM.Source2))

    Dim MB2 As New MultiBinding With {.Converter = MB.Converter}
    MB2.Bindings.Add(Source2Binding)
    MB2.Bindings.Add(MB.Bindings(1))
    MB2.Bindings.Add(MB.Bindings(2))

    Control.SetBinding(System.Windows.Controls.Image.SourceProperty, MB2)

    Return DT
  End Function
End Class

I have confirmed that it doesn't even assign this newly created MultiBinding to Image's Source property. What am I doing wrong?

dotNET
  • 33,414
  • 24
  • 162
  • 251

1 Answers1

1

The LoadContent() method creates an instance of the Image element that you have defined in the template. You are then setting the properties of this specific instance and return the unmodified template that you have defined in the XAML. The Image element that you modify in the SelectTemplate method will then be eligible for garbage collection immediately and will never be used.

So this approach won't work. You need to return a completely different DataTemplate from the method. You can't base a DataTemplate on another one. You might as well get rid of the DataTemplate from your XAML and use the XamlReader.Parse to create a DataTemplate dynamically in your DataTemplateSelector. Check my answer here for an example:

Combining DataTemplates at runtime

Your current approach applies the template and throws away the result.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • Hmm... Makes sense. My impression was that `LoadContent()` would load the content *within* the `DT` object (much like `XmlDocument`'s `Load`). Obviously I was wrong. For now I have defined two identical `DataTemplate`s within XAML, which only differ by that one property. I return the appropriate one based on the condition. Thanks for your input. – dotNET Nov 01 '17 at 17:37