12

I have spent all day looking for a way to display a default string of text on a ComboBox and the closest I managed to find that worked was an example that uses watermarking. When my application opens, the ComboBox's Visibility property is set to Collapsed and then made visible by a command. Unfortunately, I can't get the watermark to follow suit. Here is what I'm working with:

<Style x:Key="watermarkLabelStyle">
    <Setter Property="TextBlock.Foreground" Value="Black" />
    <Setter Property="FrameworkElement.Opacity" Value="0.8" />
    <Setter Property="TextBlock.FontSize" Value="12" />
    <Setter Property="TextBlock.FontStyle" Value="Italic" />
    <Setter Property="TextBlock.Margin" Value="8,4,4,4" />
    <Setter Property="TextBlock.Visibility" Value="{Binding Visible}" />
</Style>

{Binding Visible} has no effect even though other controls in the window are bound to it and behave properly.

<ComboBox ItemsSource="{Binding LeagueFormatsNode}"
          x:Name="leagueFormatComboBox"
          Grid.Column="0"
          Grid.Row="1"
          Grid.ColumnSpan="3"
          ScrollViewer.CanContentScroll="False"
          HorizontalContentAlignment="Stretch"
          Visibility="{Binding Visible}"
          Behaviors:WatermarkComboBoxBehavior.EnableWatermark="True"
          Behaviors:WatermarkComboBoxBehavior.Label="Select League Format"
          Behaviors:WatermarkComboBoxBehavior.LabelStyle="{StaticResource watermarkLabelStyle}" /> 

And the Visible property in the viewmodel:

public Visibility Visible
{
    get { return _visibile; }
    set
    {
        if (_visibile == value)
            return;
        _visibile = value;
        RaisePropertyChanged(() => Visible);
    }
}

What can I do to make the setter in the style behave and register the binding?

If you need additional code, I'll gladly provide it.


Update: Snoop is showing a binding error on the TextBlock's Visibility property. On the DataContext tab, it says "object is null". I have been looking for a way to fix this but I haven't been able to figure out how. If anybody would be kind enough to push me in the right direction, I would certainly appreciate it. The code came from here http://archive.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=PierreCode&ReleaseId=3546

I'm not necessarily looking for a complete walkthrough, just enough advice to guide me to the solution.

Jason D
  • 2,634
  • 6
  • 33
  • 67
  • Use Snoop to inspect the Visual Tree and see what is the `DataContext` of that element. I suspect you might also have binding errors information in the Visual Studio Output WIndow. – Federico Berasategui Jun 19 '13 at 20:35
  • When I use Snoop, this happens: `The assembly with display name 'Snoop.XmlSerializers' failed to load in the 'LoadFrom' binding context of the AppDomain with ID 1. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'Snoop.XmlSerializers, Version=2.8.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.` Snoop works fine on other applications. – Jason D Jun 19 '13 at 20:42
  • Snoop is showing a binding error on the `TextBlock`'s Visibility property. On the DataContext tab, it says "object is null". – Jason D Jun 19 '13 at 21:27
  • That's because the `TextBlock` is probably being created by the behavior. You will have to change the code in the Behavior so that the `TextBlock` recieves the same DataContext as it's AssociatedObject. – Federico Berasategui Jun 19 '13 at 21:28
  • Hmm.. This should be interesting. – Jason D Jun 19 '13 at 21:31

1 Answers1

9

Based on your posted code I'm assuming your using the Behavior from Here

Now if you download the sample zip in the above Link, you got 5 files that give you this set of Behavior's(found in the Behavior folder).

Edit TextBlockAdorner.cs

In the constructor just after the line

m_TextBlock = new TextBlock { Style = labelStyle, Text = label };

add

m_TextBlock.DataContext = adornedElement;

Now in your Style setter switch your Binding to

<Setter Property="TextBlock.Visibility"
        Value="{Binding DataContext.Visible}" />

and you should be done.

Side-Notes:

  • Do not hold System.Windows.Visibility in your VM. Keep Visibility property in the VM as a bool and when your Binding it in xaml use a BooleanToVisibilityConverter(available directly in xaml. You do not have to create one)
  • When your defining Style's get into the habit of specifying a Type="...". It not only helps identify at a glance which Style's relate to what but also saves some redundant type qualification for each of your setter properties.

so something like

<Setter Property="FrameworkElement.Opacity"
        Value="0.8" />

will be

<Style x:Key="watermarkLabelStyle"
        TargetType="{x:Type TextBlock}">
  ...
  <Setter Property="Opacity"
          Value="0.8" />
  • Finally hopefully this is just a typo in your code but if not try to follow some naming convention with your Properties. In your VM, your property is called Visible while it's private back-end is _visibile.
Viv
  • 17,170
  • 4
  • 51
  • 71
  • @JasonD you`re welcome :) do see the edit I made to my answer about some other aspects of the code you've posted and you could maybe put some of them to use. – Viv Jun 19 '13 at 22:16
  • Crap. That was a typo. Thanks for the advice... I'm still getting the hang of things but learning more every day. – Jason D Jun 19 '13 at 22:23