Search code examples
c#wpfdata-bindingresourcedictionarylate-binding

Late Binding, or accessing a page element from its resource dictionary


As a simple example, I have a button in a resource dictionary, which I will store in a ContentControl. I need a to bind the Button's Visibility property to a checkbox located on the page, but the button is created before the checkbox, so my setter won't work.

Is there a way to make a binding bind after the page is initialized? I know I can do it from the code behind, but I'll have a lot of buttons, and it seems rather messy to have parts of the buttons' initialization code in different locations.

<ResourceDictionary>
<button  x:Key = "MyButton">Hi There
<button.Style>
    <Style>
        <Setter Property="IsVisible" Value="false"/>
        <DataTrigger     // myCheckBox doesn't exist yet...
          Binding="{Binding ElementName=myCheckBox, Path=IsChecked}" Value="True">
            <Setter Property="IsVisible" Value="true"/>
        <DataTrigger/>
    </Style>
</button.Style>
</button>
</ResourceDictionary>

<Grid>
<Grid.RowDefinitions>
    <RowDefinition Height="1*"/>
    <RowDefinition Height="1*"/>
    <RowDefinition Height="1*"/>
 </Grid.RowDefinitions>

    <CheckBox x:Name = "myCheckBox" Row=1/> //This is made too late to bind my button to

    <ContentControl Content = "{StaticResource MyButton}" Row=2/>

</Grid>

I've found things like lazy loading, where you load objects when you need them, and I've explored making my own binding class, but I just don't know where to go with it.

My current favorite idea is something like:

xaml:

property="{lateBinding source=whatever path=you.want}"

and some generic c# class code:

class lateBinding : Binding
{
    OnPageInitialized()
    {
        SetBinding(myObject, myProperty, myBinding);
    }
}

Any Ideas?


Solution

  • Your code works with little changes

    <Window x:Class="WpfApplication11.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <ResourceDictionary>
                <Button  x:Key = "MyButton">Hi There
                    <Button.Style>
                        <Style TargetType="{x:Type Button}">
                            <Style.Triggers>
                                <DataTrigger  Binding="{Binding ElementName=myCheckBox, Path=IsChecked}" Value="True">
                                    <Setter Property="Visibility" Value="Visible"/>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding ElementName=myCheckBox, Path=IsChecked}" Value="False">
                                    <Setter Property="Visibility" Value="Collapsed"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Button.Style>
                </Button>
            </ResourceDictionary>
        </Window.Resources>
    
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>
    
            <CheckBox x:Name = "myCheckBox" Grid.Row="1"/> 
    
            <ContentControl Content = "{StaticResource MyButton}" Grid.Row="2"/>
    
        </Grid>
    </Window>