Search code examples
wpfxamldatatemplatedatatriggersetter

Setting the tag property of a button to an integer value and firing a trigger


I want to do something like the following but it doesn't work. I want to use a datatrigger to set an integer (or whatever type) value to the Tag Property of a button i define inside my datatemplate. And then inside the button's image style fire a trigger when the corresponding value is set to the tag property of the button. But it doesn't seem to be working this way. If i set an x:Null value i can fire the trigger, that means the logic is ok. But setting a value like 0 or 1 doesn't fire the trigger. Any solutions?

<DataTemplate x:Key="SomeDataTemplateofSomeType">

<Button x:Name="ButtonVisible">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Image x:Name="FxImage">
                  <Image.Style>
                      <Style TargetType="{x:Type Image}">
                        <Style.Triggers>
                           <DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource TemplatedParent},UpdateSourceTrigger=PropertyChanged}" Value="0">
                               <Setter Property="Source" Value="/Resources/controls/images/fxiconsnone.png" />
                           </DataTrigger>
                        </Style.Triggers>
                      </Style>
                 </Image.Style>
            </Image>
        </ControlTemplate>
   </Button.Template>
</Button>

<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsVisible, Value="True">
    <Setter Property="Tag" TargetName="ButtonVisible" Value="1" />
</DataTrigger>

<DataTrigger Binding="{Binding Path=IsVisible, Value="False">
    <Setter Property="Tag" TargetName="ButtonVisible" Value="0" />
</DataTrigger>
</DataTemplate.Triggers>
</Datatemplate>

Solution

  • You are binding to the DataContext of the Image and not to the templated Button

    Bind to the TemplatedParent instead.

    On a side note, there is no need to use two DataTriggers for true and false. Do this instead

    <Button x:Name="ButtonVisible" Tag="1">
    

    And only keep one of the DataTriggers

    <DataTrigger Binding="{Binding Path=IsVisible}" Value="False">
        <Setter Property="Tag" TargetName="ButtonVisible" Value="0" />
    </DataTrigger>
    

    Example, add the following to MainWindow.xaml

    <StackPanel>
        <StackPanel.Resources>
            <DataTemplate x:Key="SomeDataTemplateofSomeType">
                <Button x:Name="ButtonVisible">
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Image x:Name="FxImage">
                                <Image.Style>
                                    <Style TargetType="{x:Type Image}">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource TemplatedParent},UpdateSourceTrigger=PropertyChanged}" Value="0">
                                                <Setter Property="Source" Value="YourImageSource" />
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </Image.Style>
                            </Image>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding Path=IsVisible}" Value="True">
                        <Setter Property="Tag" TargetName="ButtonVisible" Value="1" />
                    </DataTrigger> 
                    <DataTrigger Binding="{Binding Path=IsVisible}" Value="False">
                        <Setter Property="Tag" TargetName="ButtonVisible" Value="0" />
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </StackPanel.Resources>
        <ContentControl Content="{Binding MySource}"
                        ContentTemplate="{StaticResource SomeDataTemplateofSomeType}"/>
        <ToggleButton IsChecked="{Binding Path=MySource.IsVisible, Mode=TwoWay}" Content="IsChecked?"/>
    </StackPanel>
    

    MainWindow.xaml.cs

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            MySource = new MySource();
    
            this.DataContext = this;
        }
        public MySource MySource
        {
            get;
            set;
        }
    }
    public class MySource : INotifyPropertyChanged
    {
        private bool m_isVisible;
        public bool IsVisible
        {
            get { return m_isVisible; }
            set
            {
                m_isVisible = value;
                OnPropertyChanged("IsVisible");
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }