Reputation:
I'm pretty new to WPF -- tantalized by the possibilities, but getting frustrated.... I'm trying to make it so different tabs on a TabControl have different foregound/background colors according to when they're selected. First thing I did was to create new TabItem class called PlayerTabItem and gave it a Brush SelectedBackground property. This is a music player app, so "player" in this context refers to its use in this app. (I first created SelectedBackground as a simple property, then later as a dependency property, but this didn't seem to change anything, so I have omitted that implementation.)
class PlayerTabItem : TabItem
{
public Brush SelectedBackground { get; set; }
}
Then I used this is in my XAML, and it compiled okay (so long as I put "local:" in front of the tag name), and recognized the new property I created. Of course, the property didn't do anything. This is where I got stuck.
<local:PlayerTabItem Header="Now Playing" SelectedBackground="Blue"/>
<local:PlayerTabItem Header="Collection" SelectedBackground="Purple"/>
<local:PlayerTabItem Header="Search" SelectedBackground="Green"/>
I tried handling selection events in the PlayerTabItem class in order to apply the background color, but this was a dead end. (Overriding PlayerTabItem.OnSelected and setting color there had no effect -- ran without error but did nothing.) Then I tried adding a Style with a new ControlTemplate and a Trigger for IsSelected = true, and I started getting closer....it worked if I just hard-coded a color in the Trigger.Setter:
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="Purple" />
</Trigger>
But what I really want is to bind to the PlayerTabItem's SelectedBackground color. I tried this:
<Setter TargetName="Panel" Property="Background" Value="{Binding SelectedBackground}" />
But it had no effect. I suspected that I needed some kind of Path argument on the binding, but I had no idea what. I tried using XAMLSpy to maybe help me see what was going on (as far as hierarchy of elements and possible binding path), but I didn't get very far with that -- except that when I tried to set the SelectedBackground property through XAMLSpy, it reported that the property SelectedBackground wasn't found. How could that be? ....since I had compiled and run the program without error.
I hope what I'm trying to do makes sense -- I just want to change the background color of selected tabs on a tab control when they are selected.
Upvotes: 0
Views: 1176
Reputation: 4913
In order to have the tab color to change, edit the template control, and remove the triggers :
In outline window right click on the PlayerTabItem : Edit Template/Edit a copy.
You could also modify the triggers to apply some style depending on focus, hover, ...
First create two dependency properties (snippet propdp + tabulation twice) in the PlayerTabItem, and listen to the changes of the IsSelected property:
class PlayerTabItem : TabItem
{
public PlayerTabItem()
{
Loaded += (sender, e) => { Background = IsSelected ? SelectedBackground : UnSelectedBackground; };
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(TabItem.IsSelectedProperty, typeof(TabItem));
dpd.AddValueChanged(this, (sender, args) =>
{
Background = IsSelected ? SelectedBackground : UnSelectedBackground;
System.Diagnostics.Debug.WriteLine("Changing background of {0} to {1}", this.Header, this.Background);
});
}
public Brush SelectedBackground
{
get { return (Brush)GetValue(SelectedBackgroundProperty); }
set { SetValue(SelectedBackgroundProperty, value); }
}
public static readonly DependencyProperty SelectedBackgroundProperty =
DependencyProperty.Register("SelectedBackground", typeof(Brush), typeof(PlayerTabItem), new PropertyMetadata(null));
public Brush UnSelectedBackground
{
get { return (Brush)GetValue(UnSelectedBackgroundProperty); }
set { SetValue(UnSelectedBackgroundProperty, value); }
}
public static readonly DependencyProperty UnSelectedBackgroundProperty =
DependencyProperty.Register("UnSelectedBackground", typeof(Brush), typeof(PlayerTabItem), new PropertyMetadata(null));
}
So the controls can be declared using the dependency properties and see the color change when selection is made
<TabControl >
<local:PlayerTabItem SelectedBackground="Red" UnSelectedBackground="Pink" Header="Tab1" Style="{DynamicResource PlayerTabItemStyle1}" />
<local:PlayerTabItem SelectedBackground="Yellow" UnSelectedBackground="Pink" Header="Tab2" Style="{DynamicResource PlayerTabItemStyle1}"/>
<local:PlayerTabItem SelectedBackground="Green" UnSelectedBackground="Pink" Header="Tab3" Style="{DynamicResource PlayerTabItemStyle1}"/>
</TabControl>
I admit that there must be a better to do it without listening to the events, just using the triggers. But I couldn't get it to work.
Note that in my sample, the colors are simple (red,...) but you could use any brush for the colors
There is a full working demo in the link here : http://1drv.ms/1NfCl9z
Best coding
Upvotes: 0