开发者

"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?


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜