2
votes

In WPF application I create Listbox with it's ItemTemplate defined in following DataTemplate in XAML:

<DataTemplate x:Key="ListItemTemplate">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"></RowDefinition>
      <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <StackPanel>
      <Button/>
      <Button/>
      <Button Name="btnRefresh" IsEnabled="false"/>
      <TextBlock/>
      <TextBlock/>
      <TextBlock/>
      <TextBlock/>
    </StackPanel>
    <TextBox/>
  </Grid>
</DataTemplate>

Once ListBox is generated I need to change following button IsEnabled propety to true on all ListBoxItem(s): <Button Name="btnRefresh" IsEnabled="false"/>

PROBLEM:

I Cannot access ListBoxItem(s) and therefore cant access their children with that button among them.

Is there in WPF anything like ListBox.Descendents() which is in Silverlight or any other way to get to that button,

2
how are you binding the ItemsSource of your ListBox?jimmyjambles
I assign object instance to ItemSource programically and than use Text="{Binding Name}" on each controlidelix
Im still not quite understanding your question, have you tried binding IsEnabled="{Binding IsObjectEnabled}" and adding that accessor to the object you are populating the listbox with?jimmyjambles

2 Answers

7
votes

The preferred way to do this is by changing a property in the ViewModel that is bound to that Button's IsEnabled property. Add a handler to the ListBox.Loaded event and set that property in the ViewModel to false when the ListBox is loaded.

The other option, if you need to traverse through each data templated item in the ListBox then do the following:

    if (listBox.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
        {
           foreach (var item in listBox.Items)
           {
              ListBoxItem container = listBox.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
              // Get button
              ContentPresenter contentPresenter = contentPresenter.ContentTemplate.FindName("btnRefresh", contentPresenter);
              Button btn = contentPresenter as Button;
              if (btn != null)
                  btn.IsEnabled = true;
           }
        }
3
votes

If all you need is enabling the button in the ListBoxItem, there is a XAML solution. Use DataTemplate.Triggers:

<DataTemplate.Triggers>
    <DataTrigger Binding="{Binding RelativeSource=
        {RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
        <Setter TargetName="btnRefresh" Property="IsEnabled" Value="true"/>
    </DataTrigger>
</DataTemplate.Triggers>

In this way, whenever a ListBoxItem is selected, the button on that item will be enabled. No c# code is needed. Simple and clean.

More details can be found at : http://wpftutorial.net/DataTemplates.html