views:

297

answers:

1

I have a style xaml resource dictionary which is added in Application.xaml. In that style file I specify that all textblocks should have the foreground white. The problem is that this will change the combobox items foreground to white in a usercontrol I have in the same application. I want the items to have a black foreground in all or only this one combobox. I'm having big troubles making that happen.

This is my global style for textblocks:

 <Style TargetType="{x:Type TextBlock}" >
        <Setter Property="Foreground">
            <Setter.Value>
                White
            </Setter.Value>
        </Setter>
        <Setter Property="Height">
            <Setter.Value>
                23
            </Setter.Value>
        </Setter>
  </Style>

Also: The usercontrol adds the combobox dynamically in the code-behind.

Can this be done? How?

I've made changes according to Ray Burns comment. This is my MyCustomStyler:

Public Class MyCustomStyler
    Inherits DependencyObject

    Public Shared Function GetStyle1(ByVal obj As DependencyObject) As Style
        Return obj.GetValue(Style1Property)
    End Function
    Public Shared Sub SetStyle1(ByVal obj As DependencyObject, ByVal value As Style)
        obj.SetValue(Style1Property, value)
    End Sub

    Public Shared instancePropertyChangedCallback As New PropertyChangedCallback(AddressOf PropertyChangedCallback_Handler)

    Public Shared ReadOnly Style1Property As DependencyProperty = _
                           DependencyProperty.RegisterAttached("Style1", _
                           GetType(Style), GetType(MyCustomStyler), _
                           New FrameworkPropertyMetadata(instancePropertyChangedCallback))

    Public Shared Sub PropertyChangedCallback_Handler(ByVal obj As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim element = CType(obj, FrameworkElement)
        Dim style = CType(e.NewValue, Style)
        element.Resources(style.TargetType) = style
    End Sub

End Class

This is my style section:

<Style TargetType="ComboBox">
        <Setter Property="local:MyCustomStyler.Style1">
            <Setter.Value>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="Foreground" Value="Black" />
                </Style>
            </Setter.Value>
        </Setter>
    </Style>

Can't get it to work though.. Still white foreground...

+2  A: 

The way to look at this question is: How can I make ComboBoxes use a different TextBox style than the rest of my UI?

The answer is: Create an attached property that applies the other style, then use a ComboBox style to apply your attached property.

First the ComboBox style so you'll see where this is headed:

<Style TargetType="ComboBox">
  <Setter Property="local:MyCustomStyler.Style1">
    <Setter.Value>
      <Style TargetType="TextBox">
        <Setter Property="Background" Value="Black" />
      </Style>
    </Setter.Value>
  </Setter>
</Style>

Now for this to work you'll need to define the MyCustomStyler class, which will be something like this:

public class MyCustomStyler
{
  public static Style GetStyle1(DependencyObject obj) { return (Style)obj.GetValue(Style1Property); } 
  public static void SetStyle1(DependencyObject obj, Style value) { obj.SetValue(Style1Property, value); } 
  public static readonly DependencyProperty Style1Property = DependencyProperty.RegisterAttached("Style1", typeof(Style), typeof(MyCustomStyler), new PropertyMetadata 
  { 
    PropertyChangedCallback = (obj, e) => 
    {
      var element = obj as FrameworkElement;
      var style = e.NewValue as Style;
      element.Resources[style.TargetType] = style;
    }
  });
}

The way this works is, every time you set the attached Style1 property on a FrameworkElement (such as a ComboBox), it adds the style to the Resources under the default key. So whenever the above-shown Style is applied to a ComboBox, the internal TextBox style will be added to the ComboBox's resources, causing the TextBox to get this style.

From here it is simple to achieve what you are looking for: Just put the ComboBox style in your App.xaml alongside your custom TextBox style and you're done.

Ray Burns
I've added the style code to my application wide styles.xaml and added a MyCustomStyler but it still doesn't work.None of my breakpoints inside the properties or the propertychangedcallback gets hit.See the code in my first reply.
Christian80
I changed the style code to the one I have posted in my comment. Changed from targettype=TextBox to TextBlock. Now the PropertyChangedCallback is being hit and the style is added to the element but still white text instead of black. This is strange!
Christian80