Question

I have a piece of code that is almost identical to another -- they both follow, more or less, the same exact template...

<Style TargetType="{x:Type controls:LookupControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:LookupControl}">
                <controls:AutoCompleteTextBox Margin="5,2,2,2"
                                              EntityItemTemplate="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                                           Path=ItemTemplate,
                                                                           Mode=TwoWay,
                                                                           UpdateSourceTrigger=PropertyChanged}"
                                              Items="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                              Path=SearchResults}"
                                              SelectAllOnFocus="True"
                                              Text="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                             Path=Text,
                                                             Mode=TwoWay,
                                                             UpdateSourceTrigger=PropertyChanged}"
                                              Watermark="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                                  Path=Watermark,
                                                                  Mode=TwoWay}"
                                              Value="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                              Path=Value,
                                                              Mode=TwoWay,
                                                              UpdateSourceTrigger=PropertyChanged}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

and

<Style TargetType="{x:Type controls:SomeEntityControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:SomeEntityControl}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>

                    <TextBlock Grid.Row="0"
                               Margin="2"
                               Style="{DynamicResource InputTitle}"
                               Text="{Binding RelativeSource={RelativeSource TemplatedParent},
                                              Path=Label,
                                              Mode=TwoWay,
                                              UpdateSourceTrigger=PropertyChanged}" />

                    <controls:AutoCompleteTextBox Grid.Row="1"
                                                  Margin="5,2,2,2"
                                                  DisplayMemberPath="Name"
                                                  Items="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                                  Path=SomeEntities}"
                                                  SearchMemberPath="Name"
                                                  SelectAllOnFocus="True"
                                                  Text="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                                 Path=Text,
                                                                 Mode=TwoWay,
                                                                 UpdateSourceTrigger=PropertyChanged}"
                                                  Value="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                                  Path=Value,
                                                                  Mode=TwoWay,
                                                                  UpdateSourceTrigger=PropertyChanged}">
                        <controls:AutoCompleteTextBox.EntityItemTemplate>
                            <DataTemplate DataType="{x:Type entities:SomeEntity}">
                                <TextBlock Text="{Binding Name}" />
                            </DataTemplate>
                        </controls:AutoCompleteTextBox.EntityItemTemplate>
                    </controls:AutoCompleteTextBox>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

They are almost identical -- and the first is the one causing me issues. Everything binds correctly in Snoop, but for some reason, Value (on LookupControl) is bound to "Local" rather than "ParentTemplate". In SomeEntityControl it is bound to ParentTemplate successfully.

The "AutoCompleteTextBox" in the LookupControl's value is Local and null. In the SomeEntityControl, it is ParentTemplate (and at least, still null -- but it changes whenever something IS selected).

There is nothing in the LookupControl that manually overrides Value and sets it as anything, which could be a potential problem. I'm just curious if I missed something. I don't understand how the TemplateBinding is being ignored by one and applied by another...

To add more detail, SomeEntityControl's value is statically typed to SomeEntity -- so the Value property on that is SomeEntity. On the other, it is of type Object. I tried swapping from type Object to string, but no luck -- it stayed bound Locally still, for some reason.

(Inside LookupControl)

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(object), typeof(LookupControl), new UIPropertyMetadata(null));

(Inside SomeEntityControl)

    public static readonly DependencyProperty ValueDependencyProperty =
        DependencyProperty.Register("Value", typeof(SomeEntity), typeof(SomeEntityControl), new UIPropertyMetadata(null));

Any thoughts? I know for sure the Style's are being set correctly... I know that it SHOULD be bound -- there are no errors/exceptions to show a problem occuring in the Tracer/Output window on the Value property on LookupControl...

I'm wondering if there is potentially a weird error that if a TemplateParent isn't found that it reverts to local or something...?

Was it helpful?

Solution

I just wanted to follow up with the solution, since someone else may have run into it and been wondering, "What did he find?!?! What is the answer?"

I fixed it by rewriting the control and it's XAML, starting over completely new. In the end, the details look almost the exact same to the naked eye. I would like to emphasize, though, that this time through, I had minimal functionality and added in all of the other "nice to have's" slowly (rather than incorporating them all at the same time).

I held the code on two monitors and they looked identical... but for some reason the "new" version works. Unfortunately, that probably doesn't help out anyone, but it was the "answer." Had I been less gung-ho, I probably could have stripped the functionality out and then reintegrated it back in slowly to diagnose the issue. Sometimes, starting back from scratch helps you avoid pitfalls, though.

OTHER TIPS

Just in case other people like me stumble upon this post. This is most probably not an issue with the XAML but with an internal code behind call to a dependency property setter. Using "SetCurrentValue" for such internal "setter" should not affect the value source.

Thanks Sean for pointing me in the right direction: https://wpf.2000things.com/2010/12/06/147-use-setcurrentvalue-when-you-want-to-set-a-dependency-property-value-from-within-a-control/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top