Waseem Sadiq

Hello all,

I have been wrestling with the issue of getting databinding to work, hope that somebody can help me out here.

I have a ListBox which is bound to an ObservableCollection of T (exposed by the Collection property of my window). T has an associated DataTemplate. Here is the simplified version of my app:

<Window.Resources>

<DataTemplate x:Key="StartTemplate">

<Button Command="local:BatchRunnerCommands.StartCommand" CommandParameter="{Binding}" />

</DataTemplate>

<DataTemplate x:Key="StopTemplate">

<Button Command="local:BatchRunnerCommands.StopCommand" CommandParameter="{Binding}" />

</DataTemplate>

<DataTemplate DataType="{x:Type local:MyType}">

<ContentPresenter

Content="{Binding}"

ContentTemplateSelector="{StaticResource StatusTemplateSelector}" />

</DataTemplate>

</Window.Resources>

<ListBox ItemsSource="{Binding Collection}" Width="Auto">

</ListBox>

My DataTemplate has a ContentPresenter which looks at my business object and returns a specific Sub-DataTemplate, which in turn is displayed.

So far, so good. But if you look closely at the Content binding of the ContentPresenter, it is bound directly to the business object. The reason that I did this was that in my sub-DataTemplate (called StartTemplate and StopTemplate) I have a Button which has the CommandParameter bound to my business object. Using this approach I can easily perform actions on my business object in my event handlers.

public void ExecuteStartCommand(object sender, ExecutedRoutedEventArgs e)

{

BusinessObject obj = (BusinessObject) e.Parameter;

obj.DoSomething();
obj.SomeProperty = "blah"; // No refresh here

}

The problem is that if I change a property in my business-object, the ContentPresenter will not re-evaluate the bound business object. I do have an INotifyPropertyChanged but since the ContentPresenter looks directly at the business object (and not at a property, that is done by the sub-DataTemplate) it is simply ignored (by design).

I tried cooking up a solution by binding the CommandParameter property of the button to the RelativeSource, but that doesn't seem to work.

I also thought about calling UpdateSource on the ContentPresenter directly, but as I don't have a reference to this in my command handler this is also kind of trick.

Does anybody have an idea about how to either get the Button to bind to the businessobject and have the ContentPresenter look at a property (with change notification); or force the ConcentPresenter to re-evaluate it's binding in some other way

Thanks,

Waseem



Re: Windows Presentation Foundation (WPF) How to bind to parent from inside a DataTemplate

Josh Smith

I just posted a blog entry about how to solve this problem, along with a demo app: http://joshsmithonwpf.wordpress.com/2007/03/18/updating-the-ui-when-binding-directly-to-business-objects-that-are-modified/

HTH






Re: Windows Presentation Foundation (WPF) How to bind to parent from inside a DataTemplate

Waseem Sadiq

Hi Josh,

Thanks a lot! I will try out your solution in the morning. Nice post also.

- Waseem





Re: Windows Presentation Foundation (WPF) How to bind to parent from inside a DataTemplate

Neil Mosafi

Hmm interesting solution but I am not sure if this is a bug I think the crux of the issue is that a template which is selected by a DataTemplateSelector is not re-evaluated once the template is selected.

The wrapper solution is a good workaround but it would mean that if any property on the bound data object changes, the binding would be reevaluated, which could have performance penalties.

I rarely use a DataTemplateSelector in a situation where the DataTemplate might change. Why not use a trigger, something like follows:

        <DataTemplate DataType="{x:Type local:MyType}">

            <ContentPresenter Content="{Binding}" Name="cp" />

            <DataTemplate.Triggers>

                <DataTrigger Binding="{Binding Path=IsRunning}" Value="True">

                    <Setter TargetName="cp" Property="ContentTemplate" Value="{StaticResource StopTemplate}" />

                </DataTrigger>

                <DataTrigger Binding="{Binding Path=IsRunning}" Value="False">

                    <Setter TargetName="cp" Property="ContentTemplate" Value="{StaticResource StartTemplate}" />

                </DataTrigger>

            </DataTemplate.Triggers>

        </DataTemplate>







Re: Windows Presentation Foundation (WPF) How to bind to parent from inside a DataTemplate

SerialSeb

I'll have to side with Neil on that one.

Don't think it can be classified as a bug, indeed because a TemplateSelector has no reason to re-evaluate an object when properties change. It's there to choose which template gets applied to an object, and shouldnt really be used to dynamically change the template based on values.

Think templates in xsl and we're getting quite close to what exists in wpf.






Re: Windows Presentation Foundation (WPF) How to bind to parent from inside a DataTemplate

Josh Smith

I don't think it's a bug in WPF either. In my blog post when I said that the issue being worked around was a bug, I meant that it was a bug in the application, not in the platform.