1

I am currently using the code from this blogpost in order to have my TreeView highlight those items, which are currently hovered by the mouse. This is working as intended, however now I want the TreeViewItems to notify their attached ViewModels when they are hovered / not hovered.

However I'm at a loss on how I can achieve this. The corresponding XAML code looks like the following:

<Style TargetType="{x:Type TreeViewItem}">
    <Style.Triggers>
        <Trigger Property="Controls:TreeViewHelper.IsMouseDirectlyOverItem" Value="True">
            <Setter Property="Background" Value="Green" />
        </Trigger>
    </Stile.Triggers>
</Style>

How can I bind the property from my ViewModel, named TreeNodeModel.IsHovered to the TreeViewItem (or probably the attached dependency property IsMouseDirectlyOverItem) so that I can react on those changes from within my code?

All the examples I found via google only explained how the set the background color. Thanks in advance for your time on the probably trivial answer.

Simon
  • 428
  • 5
  • 19

1 Answers1

1

In your Style, try adding a Setter which binds IsMouseDirectlyOverItem to IsHovered, and use the OneWayToSource binding mode to push the value the right way:

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="Controls:TreeViewHelper.IsMouseDirectlyOverItem"
            Value="{Binding Path=IsHovered, Mode=OneWayToSource}" />

    <Style.Triggers>
        ...
</Style>

EDIT: As IsMouseDirectlyOver is read-only, and read-only DPs can't be the target of any bindings, Fredrik Hedblad's PushBinding may be a possible workaround: OneWayToSource Binding for ReadOnly Dependency Property

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="pb:PushBindingManager.StylePushBindings">
        <Setter.Value>
            <pb:PushBindingCollection>
                <pb:PushBinding TargetDependencyProperty="Controls:TreeViewHelper.IsMouseDirectlyOverItem" 
                                Path="IsHovered" />
            </pb:PushBindingCollection>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        ...
</Style>
Sphinxxx
  • 12,484
  • 4
  • 54
  • 84
  • I tried that, but I get an exception when running the program "Additional information: 'Setter' object cannot specify value for read-only property 'IsMouseDirectlyOverItem'". The exception makes sense since the property really is read-only. Changing it to read/write doesn't seem logical to me. Is there any other way to notify my viewmodel? – Simon Apr 19 '13 at 22:25
  • 1
    Hm.. If you don't want to change `IsMouseDirectlyOver` to read/write, this answer to a related SO question may have a workaround for you: [OneWayToSource binding from readonly property in Xaml](http://stackoverflow.com/questions/658170/onewaytosource-binding-from-readonly-property-in-xaml#answer-7227295) – Sphinxxx Apr 20 '13 at 07:36
  • 1
    ..and also read the "Update: Using PushBinding in a Style" section in Hedblad's accompanying blog post: [OneWayToSource Binding for ReadOnly Dependency Property](http://meleak.wordpress.com/2011/08/28/onewaytosource-binding-for-readonly-dependency-property/). – Sphinxxx Apr 20 '13 at 07:44
  • Took me some time to start trying this one out. However I still cannot get it to work. I think it boils down to the fact that I'm unable to specify an attached read only property (which the aforementioned IsMouseDirectlyOverItem is) as the TargetProperty in a PushBinding, nor can I specify a Binding in the Path, which I suspect I need to do, since I want it to notify my view model. I guess I'll use code behind for now. But thank you for your help. – Simon Apr 23 '13 at 18:43
  • 1
    As I understand it, you should simply set `Path="IsHovered"`, but `TargetProperty` will still give you trouble. Reading the PushBinding code I see that TargetProperty is just a string, so specifying an attached property won't work out-of-the-box. But I see that PushBinding also has a `TargetDependencyProperty` which can be used instead of TargetProperty. If you feel like having another go at it, maybe something like this would work: `` – Sphinxxx Apr 23 '13 at 22:32
  • Thank you for your persistence. Your suggestions works, in that it compiles, however I'm unable to find the correct xaml section where I should put this code. I've currently put the push binding in the ItemTemplate section of my tree view. I got no binding errors an it seemed to work, as the IsHovered property of my models are invoked, however only once with false. Subsequently hovering the mouse over an item causes the attached DP to change its value, however IsHovered is not invoked again. I'm at a loss at what could be the reason for this behaviour. – Simon Apr 24 '13 at 06:37
  • 1
    It should definitely _not_ be in the ItemTemplate, because ItemTemplate doesn't really know anything about the TreeViewItem - only the bound data (ViewModel). It should go in the TreeViewItem `Style` (where you tried the Trigger). I have updated my answer with a proposed solution. – Sphinxxx Apr 24 '13 at 07:22
  • I suspected as much, but I struggled with putting it into the styles section. Your solution works wonderfully, thank you so much. – Simon Apr 24 '13 at 07:29