Search code examples
c#wpfcode-behinditemscontrol

How to reference another control in my Items Control from Code Behind?


Here is my XAML:

<ItemsControl  Margin="0 0 0 0" Name="CtrlOrderDetails" AlternationCount="2">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid x:Name="Foobar">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                                <ColumnDefinition Width="10"></ColumnDefinition>
                                <ColumnDefinition Width="100"></ColumnDefinition>
                                <ColumnDefinition Width="10"></ColumnDefinition>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                      </Grid.ColumnDefinitions>

                      <TextBlock Grid.Column="0" Margin="0 5 0 5" FontSize="16" Text="{Binding DrugName}"></TextBlock>
                      <TextBox Grid.Column="2" FontSize="10" Width="100" Height="20" HorizontalContentAlignment="Center" HorizontalAlignment="Center" VerticalContentAlignment="Center" VerticalAlignment="Center" Tag="{Binding BarCode}" 
                                     Text="Enter Barcode.." LostFocus="BarcodeTextBox_OnLostFocus"></TextBox>
                      <CheckBox x:Name="IsGoodCheckBox" Grid.Column="4" IsEnabled="False" VerticalAlignment="Center"></CheckBox>
                  </Grid>
                  <DataTemplate.Triggers>
                      <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                                <Setter Property="Background" Value="LightGray"  TargetName="Foobar"></Setter>
                      </Trigger>
                  </DataTemplate.Triggers>
            </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

What I want to happen is that when the user enters the barcode in the textbox, if it matches the value in the Tag property then the checkbox should be set to checked.

Here is my code behind:

  private void BarcodeTextBox_OnLostFocus(object sender, RoutedEventArgs e)
    {
        var tb = sender as TextBox;
        ContentPresenter contentPresenter = FindVisualChild<ContentPresenter>(CtrlOrderDetails);
        DataTemplate yourDataTemplate = contentPresenter.ContentTemplate;
        CheckBox thisCheckBox = yourDataTemplate.FindName("IsGoodCheckBox", contentPresenter) as CheckBox;
        if (tb.Text == tb.Tag.ToString())
        {
            thisCheckBox.IsChecked = true;
        }
        else
        {
            thisCheckBox.IsChecked = false;
        }
    }

   public TChildItem FindVisualChild<TChildItem>(DependencyObject obj) where TChildItem : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            var child = VisualTreeHelper.GetChild(obj, i);

            if (child != null && child is TChildItem)
                return (TChildItem)child;

            var childOfChild = FindVisualChild<TChildItem>(child);

            if (childOfChild != null)
                return childOfChild;
        }

        return null;
    }

If I try it on the first row in my list, it works great. But, If I try it on the second row, it effects the checkbox in the first row again.

Obviously, my code does not which row I am on. How could I do that?

Thanks


Solution

  • Try this:

    private void BarcodeTextBox_OnLostFocus(object sender, RoutedEventArgs e)
    {
        var tb = sender as TextBox;
        Panel grid = tb.Parent as Panel;
        if (grid != null)
        {
            CheckBox checkBox = grid.Children.OfType<CheckBox>().FirstOrDefault(x => x.Name == "IsGoodCheckBox");
            if (checkBox != null)
            {
                //set the IsChecked property based on your logic here...
                checkBox.IsChecked = tb.Text == tb.Tag.ToString();
            }
        }
    }