locked
Data Binding to a custom Class in a DataTemplate RRS feed

  • Question

  • Hey...  (had posted this in C#, but realized here is probably more appropriate, so I deleted it from there and reposted here)

    I've made a class, inherited from FrameworkElement, that has dependency properties.  I'm trying to declare an instance of it as the tag of a button.  That much works just fine, and I am able to set and retrieve the values.  What *doesn't* work is when I try to set values of the class with data binding (with the button being inside a DataTemplate), rather than with values typed directly into the XAML.  The data binding works for other properties of the button, just not in my class inside the tag.

    Snippet of the class in question:
    Code Snippet

        public class MyCmd : FrameworkElement

    {

            public static readonly DependencyProperty ParamProperty =
                        DependencyProperty.Register(
                                "Param",
                                typeof(int),
                                typeof(MyCmd),

                                new PropertyMetadata(0, new PropertyChangedCallback(OnParamChangedCallback)));
          
     public MyCmd() : base(){}

            public int Param
            {
                get { return (int)this.GetValue(ParamProperty); }
                set { this.SetValue(ParamProperty, value);}
            }

            private static void OnParamChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                System.Console.WriteLine("New value=" + e.NewValue.ToString());
            }


    ...


    }



    The DataTemplate for the button
    Code Snippet

                        <DataTemplate x:Key="HappyButtonTemplate">
                            <Button Name="GameSelectButton" Content="{Binding fGame}" FontSize="16" IsEnabled="{Binding fIsPlayable}" Click="ClickCommand">
                                <Button.Tag>
                                    <src:MyCmd CmdString="play" Param="{Binding fID}"/>
                                </Button.Tag>
                            </Button>
                        </DataTemplate>


    I can confirm that fID does indeed make it this far by putting {Binding fID} as the button's content.  It does not, however, get set as the binding for my class inside the tag.

    The following, directly set (rather than with binding), *does* pass the properly bound Param to my class's property:
    Code Snippet

              <Style x:Key="ButtonCommand" TargetType="{x:Type Button}">
                    <EventSetter Event="Click" Handler="ClickCommand"/>
              </Style>     

    <Button

                Grid.Row="1"
                Grid.Column="4"
                Style="{StaticResource ButtonCommand}"
                Content="Show Leaderboard">
                <Button.Tag>
                    <src:MyCmd
                        CmdString="leaderboard"
                        Param="1"/>
                </Button.Tag>
            </Button


    Likewise, the OnParamChangedCallback is invoked for the explicitly-set version but not for the bound version.


    The code that invokes the template:
    Code Snippet

            <ListBox
                Grid.Row="0"
                Grid.Column="1"
                Background="Transparent"
                ItemTemplate="{StaticResource HappyButtonTemplate}"
                ItemsSource="{Binding Source={StaticResource gameselection}}"
                IsEnabled="True"
                Focusable="True">
            </ListBox>





    Do I have something hooked up improperly?  Am I trying to do something impossible?

    Let me know if I can supply more information that would help.

    Thanks,

    -Alex
    Tuesday, April 15, 2008 2:41 AM

Answers

  • <Button>
        <Button.Tag>
        <src:MyCmd CmdString="play" Param="{Binding fID}"/>
       </Button.Tag>
    </Button>

    The above syntax will not work for data binding, because the data binding engine will always need to the correct FrameworkElement.DataContext to be set or propagated down the element tree or cross inheritence contexts. But MyCmd is not part of the element tree, and inheritence context mechanism is not supported for Tag property. That's why the binding
    Param="{Binding fID}" will always fails, you might need to try fixing this problem by setting the binding at code behind if possible.

    BTW, could you please elaborate what type of binding data scenario you want to enable, we might be able to come up with a WPF friendly solution for you.

    Hope this helps
                         

    Thursday, April 17, 2008 2:38 AM

All replies

  • <Button>
        <Button.Tag>
        <src:MyCmd CmdString="play" Param="{Binding fID}"/>
       </Button.Tag>
    </Button>

    The above syntax will not work for data binding, because the data binding engine will always need to the correct FrameworkElement.DataContext to be set or propagated down the element tree or cross inheritence contexts. But MyCmd is not part of the element tree, and inheritence context mechanism is not supported for Tag property. That's why the binding
    Param="{Binding fID}" will always fails, you might need to try fixing this problem by setting the binding at code behind if possible.

    BTW, could you please elaborate what type of binding data scenario you want to enable, we might be able to come up with a WPF friendly solution for you.

    Hope this helps
                         

    Thursday, April 17, 2008 2:38 AM
  • Hey, thanks for the reply.

     

    I ended up dropping this approach entirely and writing a custom control that inherits from button and defines the extra properties, which does everything I wanted *and* makes the XAML more elegant and easy to read.  All is happy now.

     

    -Alex

    Thursday, April 17, 2008 2:43 AM