none
Trigger the background of a Grid with a boolean in the DataContext (a ViewModel)

    Question

  • Hello

    I want to change the background of a Grid with a trigger. The bool is in the page its viewmodel. I already tried something like this:

            <Style x:Key="highlightStyle" TargetType="{x:Type Grid}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsHighlighted}" Value="true">
                        <Setter Property="Background" Value="Black"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </UserControl.Resources>

    the grid:

        <Grid Background="Transparent" Style="{StaticResource highlightStyle}" x:Name="gridFct">

    This is obviously not possible because IsHighlighted isn't a dependency property. I tried to find out how to do this, but I can't seem to get the dependency property right. I tried looking at several exemples on the internet, but I didn't really understand how these properties really work. Maybe there is an easier solution to do this?

    Thanks in advance

    Joachim
    Wednesday, March 03, 2010 4:23 PM

Answers

  • solved. In an underlying Canvas, the Background property was already bound to a property from the viewmodel. This seemed to override what was in the Style.
    • Marked as answer by Linda Liu Monday, March 08, 2010 5:27 AM
    Thursday, March 04, 2010 8:36 AM
  • The Grid I wanted to set this for contains a Border. This border has the Canvas as a child. Now the trigger works on the canvas itself (I think that it was also wrong to set a trigger on the grid). I couldn't solve that background issue (it kept showing the databound Background of the canvas) , but now I use a bitmapeffect to highlight the item (setting the background property was just a test to see if the trigger would work).

    That turned out to be a better way to highlight the canvas.
    • Marked as answer by Linda Liu Monday, March 08, 2010 5:27 AM
    Thursday, March 04, 2010 10:02 AM

All replies

  • Hi,

    for change notifications in the ViewModel, you have two options: implementing INotifyPropertyChanged and raising a PropertyChanged event with the property's name as an argument, or deriving the ViewModel from DependencyObject and creating a custom dependency property.

    This is an example for implementing INotifyPropertyChanged:

    Public Class BindableObject
        Implements System.ComponentModel.INotifyPropertyChanged
    
        Private _BindableProperty As Boolean
        Public Property BindableProperty() As Boolean
            Get
                Return _BindableProperty
            End Get
            Set(ByVal value As Boolean)
                _BindableProperty = value
                OnPropertyChanged("BindableProperty")
            End Set
        End Property
    
    #Region "NotifyPropertyChanged support"
        Protected Overridable Sub OnPropertyChanged(ByVal ParamArray propertynames() As String)
            If propertynames.Length = 0 Then
                RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(""))
            Else
    
                For Each propertyName As String In propertynames
                    RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
                Next
            End If
        End Sub
    
        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    #End Region
    End Class
    
    and this would be the option using a DependencyObject:

    Public Class Actions
        Inherits DependencyObject
    
        Public Shared ReadOnly BindableProperty As DependencyProperty = DependencyProperty.Register("Bindable", GetType(Boolean), GetType(Actions))
        Public Property Bindable() As Boolean
            Get
                Return GetValue(BindableProperty)
            End Get
            Set(ByVal value As Boolean)
                SetValue(BindableProperty, value)
            End Set
        End Property
    
    
    End Class
    You can find the specifics on this in the chapters on data binding and custom dependency properties in the WPF documentation.
    http://wpfglue.wordpress.com
    Wednesday, March 03, 2010 4:49 PM
  • Thanks for the answer , I'll try the one with the dependencyobject when I'm at work tomorrow. I don't think the first example would work in my case, because in the XAML code, I still would have to refer to a "normal" property (and this isn't possible when used in a style)
    Wednesday, March 03, 2010 6:29 PM
  • Hi,

    looks like a misunderstanding here. You can use only DependencyProperties as the target property in a Style Setter, but a DataTrigger uses a Binding for its condition, so you can use anything as data source what a Binding can use in this case, even if the whole thing is embedded in a Style.
    http://wpfglue.wordpress.com
    Wednesday, March 03, 2010 6:45 PM
  • thank you. I confused the example above with another tryout I did (without the datatrigger), which gave the 'dependency property' error. That's why I thought the NotifyPropertyChanged wouldn't work in this case.
    Wednesday, March 03, 2010 7:53 PM
  • I don't see why I tried this with NotifyPropertyChanged earlier , because my viewmodel classes already implement it and use it for other properties (guess I was really tired yesterday ...). However, this still doesn't work in a style. This is the style:

        <UserControl.Resources>
            <BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
            <Style x:Key="highlightStyle" TargetType="{x:Type Grid}">
                <Style.Triggers>               
                    <DataTrigger Binding="{Binding Path=IsHighlighted}" Value="true">
                        <Setter Property="Background" Value="Black"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </UserControl.Resources>


    And I use it like this:

     <Grid x:Name="gridFct" Style="{StaticResource highlightStyle}">


    The property IsHighlighted in my viewmodel:

            public Boolean IsHighlighted
            {
                get {
                    return isHighlighted;
               
                }
                set {
                    isHighlighted = value;
                    NotifyPropertyChanged("IsHighlighted");
                }
            }

    Other properties in this viewmodel already use NotifyPropertyChanged (in your VB example, its the OnPropertyChanged method which gets the property string, in c# that appeared to be something else) which works. If I set a breakpoint in this setter here, the debugger stops at the right moment.

     However, the trigger still doesn't do anything. (And I'm sure setting the Background property would have to work because I already changed the grid's background hardcoded in XAML and saw it change). I thought the NotifyPropertyChanged method updates the XAML automatically, which it does for other properties .
    Thursday, March 04, 2010 8:21 AM
  • solved. In an underlying Canvas, the Background property was already bound to a property from the viewmodel. This seemed to override what was in the Style.
    • Marked as answer by Linda Liu Monday, March 08, 2010 5:27 AM
    Thursday, March 04, 2010 8:36 AM
  • Hi,

    glad you solved it. Property inheritance can be tricky. Just to help me (and however else reads this) understand what happened: was this Canvas inside the ControlTemplate of the control that should be highlighted, or outside of it?
    http://wpfglue.wordpress.com
    Thursday, March 04, 2010 9:08 AM
  • The Grid I wanted to set this for contains a Border. This border has the Canvas as a child. Now the trigger works on the canvas itself (I think that it was also wrong to set a trigger on the grid). I couldn't solve that background issue (it kept showing the databound Background of the canvas) , but now I use a bitmapeffect to highlight the item (setting the background property was just a test to see if the trigger would work).

    That turned out to be a better way to highlight the canvas.
    • Marked as answer by Linda Liu Monday, March 08, 2010 5:27 AM
    Thursday, March 04, 2010 10:02 AM