0
votes

I am trying to bind the SelectedItem property of a listbox to two textbox controls. These controls are located in the windows resource section. The idea is when an entry in the listbox gets selected the two textbox controls display the "blockName" and "blockHelpText" from my custom class. I load the listbox first by clicking the but1 button.

<Window.Resources>
<StackPanel x:Key="testsp" Visibility="Visible" DataContext="{Binding ElementName=lsbCommonBlocks, Path=SelectedItem, diagnostics:PresentationTraceSources.TraceLevel=High}">
        <ListBox x:Name="lsbCommonBlocks" DisplayMemberPath="BlockName" SelectionChanged="lb_sc"/>
        <Button x:Name="but1" Click="but1_click" Content="Button 1"/>
        <TextBox x:Name="txt1" Text="{Binding Path=BlockName, diagnostics:PresentationTraceSources.TraceLevel=High}"/>
        <TextBox x:Name="txt2" Text="{Binding Path=BlockHelpText, diagnostics:PresentationTraceSources.TraceLevel=High}"/>
    </StackPanel>
</Window.Resources>  
<Grid>
  <ContentControl Visibility="Visible"  x:Name="contentWorkArea" Content="{StaticResource testsp}"/>
</Grid>

I have a button who's click event ties the Itemsources property of the listbox to my custom class BlockToolBar.

BlockToolBar[] blocks = { new BlockToolBar("Block 1", "No help for this block."),
                              new BlockToolBar("Block 2", "Help."),
                              new BlockToolBar("Block 3", "Help again.") };

private void but1_click(object sender, RoutedEventArgs e)
    {
        StackPanel sp = (StackPanel)this.TryFindResource("testsp");
        ListBox lb = (ListBox)LogicalTreeHelper.FindLogicalNode(sp, "lsbCommonBlocks");
        lb.ItemsSource = blocks;
    }

public class BlockToolBar : INotifyPropertyChanged
{
    private string blockName;
    public string BlockName
    {
        get { return blockName; }
        set { 
            blockName = value;
            OnPropertyChanged(new PropertyChangedEventArgs("BlockName"));
        }
    }

    private string blockHelpText;
    public string BlockHelpText
    {
        get { return blockHelpText; }
        set { 
            blockHelpText = value;
            OnPropertyChanged(new PropertyChangedEventArgs("BlockHelpText"));
        }
    }

    public BlockToolBar()
    {
        blockName = "";
        blockHelpText = "";
    }

    public BlockToolBar(string BlockName, string BlockHelpText)
    {
        blockName = BlockName;
        blockHelpText = BlockHelpText;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, e);
    }
}

Databinding does not work: TextBox's txt1 and txt2 remain blank when I click the button. The listbox populates ok. I confirmed that I'm able to obtain the BlockToolBar properties OK by creating an event on the listbox.

Visual Studio (express) output window gives me following: System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=lsbCommonBlocks'. BindingExpression:Path=SelectedItem; DataItem=null; target element is 'StackPanel' (Name=''); target property is 'DataContext' (type 'Object')

Not sure what I'm doing wrong. I'm kind new to WPF.

If I remove the stackpanel resource (testsp) and replace the contentcontrol with the testsp controls, then the databindings work. I can also bind txt1 and txt2 directly to the BlockToolBar object in the resource but I can't seem to bind txt1/txt2 to the selecteditem if in the resource.

The reason I'm doing this is I have a complicated main window which I break up into seperate resourcedictionaries and call into my main window via contentcontrols. When I couldn't get that to work I create a simpler project to try to narrow down my problem.

1

1 Answers

0
votes

Looks like have to create binding in code. I made following changes and it worked. Thought I tried this before but...

private void but1_click(object sender, RoutedEventArgs e)
    {
        StackPanel sp = (StackPanel)this.TryFindResource("testsp");
        ListBox lb = (ListBox)LogicalTreeHelper.FindLogicalNode(sp, "lsbCommonBlocks");

        Binding myBinding = new Binding();
        myBinding.Source = lb;
        myBinding.Path = new PropertyPath("SelectedItem");
        sp.SetBinding(StackPanel.DataContextProperty, myBinding);

        lb.ItemsSource = blocks;

    }