Search code examples
wpfxamlcustom-controlsdatacontext

How do I properly set this button's binding to the parent ListView ItemsControl?


I have a custom button set up inside a ListView ItemTemplate. The Listview's ItemSource is bound to a collection of items, pretty standard. I have a few labels in the listview as well, and everything works fine except the button.

Binding the button to one of the properties won't work at all using {Binding buttonName} but it will sort of work if I use {Binding Items/buttonName, ElementName=listView} - the only problem is, when I do it this way, every single button in that listView will have the exact same buttonName.

Now the issue stems from my custom button's DataContext being set to Self; unfortunately, it has to be set to Self because the custom style I'm using needs this. If I try to change the button to a UserControl instead (with the button as a child, and the DataContext set on that), then I can't use the Command property of the button for some reason.

Here's a simplified version of my ListView making use of the custom button:

<ListView x:Name="listView" ItemsSource="{Binding MyPeopleData}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Label Content="{Binding PersonName}"/>
                <ct:RevealButton Content="{Binding Items/recommendation, ElementName=listView}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

As I said above, this will make every item in the listview use the same recommendation property rather than using it's own one. If I try to use

<ct:RevealButton Content="{Binding recommendation}"/> 

It just won't work, which makes sense given the DataContext of the custom button, which is below:

<Button x:Class="RevealButton" Width="{Binding Width}" Height="{Binding Height}" Background="{Binding ButtonBackground}" DataContext="{Binding RelativeSource={RelativeSource Self}}" Style="{DynamicResource ButtonRevealStyleC}" mc:Ignorable="d">
    <Button.ContentTemplate>
        <DataTemplate>
            <ContentPresenter Content="{TemplateBinding Content}" />
        </DataTemplate>
    </Button.ContentTemplate>

</Button>

Solution

  • So this ended up being an XY Problem. Because the modified style I was using had a poorly bound property, it was failing when the parent control didn't have a DataContext set to self. This is what it was:

    <SolidColorBrush Opacity="0.8" Color="{Binding ButtonBackground.Color}" />

    And ButtonBackground was a dependency property exposed by my custom Button, so binding the style in this way meant it only worked if the Button's context was itself. Changing it to this:

    <SolidColorBrush Opacity="0.8" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ButtonBackground.Color}" />

    Fixed the DataContext dependency, which in turn fixes the heirarchy of problems above.