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

datatemplatedatatriggersetterwpfxaml

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>

Best Answer

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));
        }
    }
}
Related Topic