开发者

WPF - Freezable in a style of a button not inheriting DataContext

开发者 https://www.devze.com 2023-02-09 06:51 出处:网络
I am modeling an attached command pattern after the AttachedCommandBehavior library here. My button looks like this:

I am modeling an attached command pattern after the AttachedCommandBehavior library here. My button looks like this:

<Button>
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="vms:Attached.Behaviors">
                <Setter.Value>
                    <vms:Behaviors>
                        <vms:Behavior Event="Click" 
                                      Command="{Binding ClickCommand}" />
                    </vms:Behaviors>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>

Everything works great, but when the setter on the Behavior is executed, the Command is null.

Behavior is a Freezable, and Behaviors is a FreezableCollection<Behavior>. It just doesn't seem to be inheriting the DataContext from the Button.

On the other hand, this works correctly:

<Button>
    <vms:Attached.Behaviors>
        <vms:Behavior Event="Click" Command="{Binding ClickCommand}" />
    </vms:Attached.Behaviors>
</Button>

Unfortunately I can't开发者_如何学C do it this way, because I need to target generated ListViewItems using ItemContainerStyle.

Is there some way to get the DataContext in the Style?


The Attached Command Behavior library is the germ of the idea that became Blend Behaviors. The Blend Behaviors are much more powerful and standardized and so I recommend you switch to using them. But whether you are using Attached Command Behavior or Blend Behaviors, the problem is essential the same: they don't work as expected when trying to set them using a style. I've solved this problem for Blend Behaviors with full support for binding in this StackOverflow answer:

  • How to add a Blend Behavior in a Style Setter

Without testing it, I guess you have to move the ACB behavior to a resource marked with x:Shared="False" in order to get the binding to work.


I had the same problem, and using RelativeSource did the trick. I'll show you my before and after code...

Before: (This DIDN'T work)

<DataTemplate x:Key="MenuNodeWithChildrenTemplate">
    <StackPanel Orientation="Horizontal"
            behaviors:EventCommand.CommandToRun="{Binding OpenMenuItem}"
            behaviors:EventCommand.EventName="MouseLeftButtonUp">
        <Label Content="{Binding Title}"/>
        <Label Content="{Binding Description}"/>
    </StackPanel>
</DataTemplate>

After: (This DOES work)

<DataTemplate x:Key="MenuNodeWithChildrenTemplate">
    <StackPanel Orientation="Horizontal"
            behaviors:EventCommand.CommandToRun="{Binding Path=DataContext.OpenMenuItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}}"
            behaviors:EventCommand.EventName="MouseLeftButtonUp">
        <Label Content="{Binding Title}"/>
        <Label Content="{Binding Description}"/>
    </StackPanel>
</DataTemplate>

You'll obviously have to tweak the parameters of the Relative Source to your specific situation. It seems that, for whatever reason, attached properties don't inherit the data context, so you have to tell if how to.

0

精彩评论

暂无评论...
验证码 换一张
取 消