Vinit Sankhe
Vinit Sankhe

Reputation: 19885

"Tag" ... Special functionality in WPF?

MSDN says "Gets or sets an arbitrary object value that can be used to store custom information about this element." which means I can store anything I want in this property.

But if you bind to this property (with property of type String having a value say "XYZ") and use it in Trigger conditions it doesn't work!

  <Trigger Property="Tag" Value="XYZ">
      <Setter Property="Background" Value="Red" />
  </Trigger>

It does not set the background red. You can try and assume myElement to be a TextBlock! Why is it like this?

Upvotes: 17

Views: 31316

Answers (3)

user1228
user1228

Reputation:

The Tag is a construct held over from Winforms days (and possibly there from before that!). It was used as a convenient place to associate an object with a UI element, such as a FileInfo with a Button, so in the Button's event handler you could simply take the event sender, cast it to a Button, then cast the Tag value to a FileInfo and you have everything you need about the file you want to open.

There is one situation, however, where I've found the Tag is useful in WPF. I've used it as a holding spot that can be accessed by a ContextMenu MenuItem, which can't use the normal RelativeSource bindings you'd use to traverse the visual tree.

<ListBox.ItemContainerStyle>
        <Style
            TargetType="ListBoxItem">
            <Setter
                Property="Tag"
                Value="{Binding ElementName=TheUserControlRootElement}" />
            <Setter
                Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem
                            Header="_Remove"
                            ToolTip="Remove this from this list"
                            CommandParameter="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
                            Command="{Binding PlacementTarget.Tag.Remove, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>

From the ContextMenu, I cannot access the Remove command which is defined in the UserControl class where this snippet is defined. But I can bind the root to the Tag of the ListBoxItem, which I can access via the ContextMenu.PlacementTarget property. The same trick can be used when binding within a ToolTip, as the same limitations apply.

Upvotes: 13

max
max

Reputation: 34407

MainWindow.xaml:

<Window x:Class="wpftest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock x:Name="test" MouseDown="test_MouseDown"
                   Tag="{Binding TestProperty}">
            <TextBlock.Style>
                <Style TargetType="{x:Type TextBlock}">
                    <Style.Triggers>
                        <Trigger Property="Tag" Value="XYZ">
                            <Setter Property="Background" Value="Red" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</Window>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        DataContext = new TestViewModel();
    }

    private void test_MouseDown(object sender, MouseButtonEventArgs e)
    {
        ((TestViewModel)DataContext).TestProperty = "XYZ";
    }

    private sealed class TestViewModel : INotifyPropertyChanged
    {
        private string _testPropertyValue;

        public string TestProperty
        {
            get { return _testPropertyValue; }
            set
            {
                _testPropertyValue = value;
                var handler = PropertyChanged;
                if(handler != null)
                    handler(this, new PropertyChangedEventArgs("TestProperty"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Updated: Tag property now is bound to TestProperty.

Upvotes: 2

Emond
Emond

Reputation: 50672

Tag has no special functionality in WPF.

This works for me:

<TextBlock Tag="{Binding Data}"
           x:Name="tb">
    <TextBlock.Style>
        <Style>
            <Style.Triggers>
                <Trigger Property="TextBlock.Tag"
                         Value="XYZ">
                     <Setter Property="TextBlock.Background"
                             Value="Lime" />
                </Trigger>
            </Style.Triggers>        
        </Style>
    </TextBlock.Style>
</TextBlock>

And setting the Data object property to "XYZ" in an event.

Upvotes: 13

Related Questions