Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding the value of a Setter Property in WPF

Tags:

c#

wpf

xaml

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.

like image 638
Jason D Avatar asked Jun 19 '13 20:06

Jason D


People also ask

How binding happens in WPF?

Data binding is a mechanism in WPF applications that provides a simple and easy way for Windows Runtime apps to display and interact with data. In this mechanism, the management of data is entirely separated from the way data. Data binding allows the flow of data between UI elements and data object on user interface.

What is binding source in WPF?

A binding source is usually a property on an object so you need to provide both the data source object and the data source property in your binding XAML. In the above example the ElementName attribute signifies that you want data from another element on the page and the Path signifies the appropriate property.

What is two way binding WPF?

In two way we can change data in sources control and target control. Target to source and source to target means if we change source control value then it will automatically change target control value. And vice-a versa for source control. That's why it's called two-way data binding.


1 Answers

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.
like image 115
Viv Avatar answered Oct 27 '22 17:10

Viv