Ryan Cromwell

I'm running into a scenario while trying to data bind a property to the result of a method within a datatemplate. The problem which can be found by running the below in XamlPad is that the Bind or evaluation of the bind appears only to happen upon the first item in the ItemsControl. I believe I understand why it's not working, but does anyone have any suggestions on how to acquire the expected outcome

If you can't see it inline, here's a link.

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WPFBindToMethodExample" SizeToContent="WidthAndHeight"
xmlnsTongue Tiedystem="clr-namespaceTongue Tiedystem;assembly=mscorlib"
>
<Window.Resources>
<XmlDataProvider x:Key="dpPeople">
<x:XData>
<People xmlns="">
<Person name="Joe Schmoe" relation="Crazy Uncle" />
<Person name="Jimmy Dean" relation="Cook" />
<Person name="John Denver" relation="Second Cousin" />
<Person name="Byron Nelson" relation="Golf Buddy" />
</People>
</x:XData>
</XmlDataProvider>
<ObjectDataProvider x:Key="randomRotation" ObjectType="{x:Type system:Random}" MethodName="Next">
<ObjectDataProvider.MethodParameters>
<system:Int32>-10</system:Int32>
<system:Int32>10</system:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<DataTemplate x:Key="personTemplate">
<Button Margin="7,7,7,7">
<Button.RenderTransform>
<RotateTransform Angle="{Binding Source={StaticResource randomRotation}}" />
</Button.RenderTransform>
<WrapPanel>
<TextBlock Text="{Binding XPath=@relation}">: </TextBlock>
<TextBlock Text="{Binding XPath=@name}" />
</WrapPanel>
</Button>
</DataTemplate>
</Window.Resources>
<Grid Background="BlanchedAlmond">
<Border Margin="5,5,5,5" BorderBrush="Black" BorderThickness="1" CornerRadius="5,5,5,5" Background="AntiqueWhite">
<ItemsControl ItemTemplate="{StaticResource personTemplate}" ItemsSource="{Binding Source={StaticResource dpPeople}, XPath=/People/Person}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Border>
</Grid>
</Window>





Re: Windows Presentation Foundation (WPF) Binding to a Method within a DataTemplate...

Drew Marsh

Yeah the problem is you're binding to a single instance of the ODP, so everyone's getting the same value. What you need to do is move the ODP into the instance of the template itself. This will add some overhead, but it's unavoidable if you want to accomplish what you're trying to do. So just do this instead:

Code Snippet

<RotateTransform>

<RotateTransform.Angle>

<Binding>

<Binding.Source>

<ObjectDataProvider ObjectType="{x:Type system:Random}" MethodName="Next">

<ObjectDataProvider.MethodParameters>

<system:Int32>-10</system:Int32>

<system:Int32>10</system:Int32>

</ObjectDataProvider.MethodParameters>

</ObjectDataProvider>

</Binding.Source>

</Binding>

</RotateTransform.Angle>

</RotateTransform>

Side note: It's funny how not random Random is. It's very common for the same result to come back for 3 of the buttons. In XAMLPad I have to refresh a lot to see any major differences. You may want to work on seeding the random in some way.

HTH,
Drew





Re: Windows Presentation Foundation (WPF) Binding to a Method within a DataTemplate...

Ryan Cromwell

I did not realize that was different. I guess I'll have to run through my books again. I used this only as an example because I felt it got the point across the best. I'm actually using it to set the certain visuals to highlight different states of items in the Itemscontrol. Would you recommend a better way Can you do something similar to Xslt where you have Template with match="element[@property='a']" and a second with [@property='b']. I'd like to understand the anticipated implementation of such a scenerio. It does seem that I should be able to apply a style based on the state, but I'm not aware of how to do that.

RE: Side Note: In this case it will be less Random because I'd assume a new instance of Random is created each time rather than maintaining a single instance throughout.




Re: Windows Presentation Foundation (WPF) Binding to a Method within a DataTemplate...

Ryan Cromwell

To make it "more" random, I created a WindowResource like this

Code Snippet

<ObjectDataProvider x:Key="rand1" ObjectType="{x:Type system:Random}" >
</ObjectDataProvider>


then created the ODP in the template itself as you suggested, but referencing the instance as below. this should keep the instance alive between items.

Code Snippet

<RotateTransform>
<RotateTransform.Angle>
<Binding>
<Binding.Source>
<ObjectDataProvider MethodName="Next" ObjectInstance="{StaticResource rand1}">
<ObjectDataProvider.MethodParameters>
<system:Int32>-10</system:Int32>
<system:Int32>10</system:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Binding.Source>
</Binding>
</RotateTransform.Angle>
</RotateTransform>