代码之家  ›  专栏  ›  技术社区  ›  Yoni

如何从代码隐藏中引用“我的项目”控件中的另一个控件?

  •  1
  • Yoni  · 技术社区  · 7 年前

    <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>
    

    我想做的是,当用户在文本框中输入条形码时,如果它与标记属性中的值匹配,那么复选框应该设置为选中。

    以下是我的代码:

      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;
        }
    

    如果我在列表的第一行尝试,效果很好。但是,如果我在第二行尝试,它会再次影响第一行中的复选框。

    显然,我的代码不知道我在哪一行。我怎么能这么做?

    3 回复  |  直到 7 年前
        1
  •  1
  •   mm8    7 年前

    试试这个:

    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();
            }
        }
    }
    
        2
  •  1
  •   15ee8f99-57ff-4f92-890c-b56153    7 年前

    这将是一种更传统的XAML方法。没有代码隐藏,只有绑定和转换器。

    <ItemsControl  Margin="0 0 0 0" Name="CtrlOrderDetails" AlternationCount="2">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DataTemplate.Resources>
                    <local:EqualityMultiConverter
                        x:Key="EqualityConverter"
                        />
                </DataTemplate.Resources>
    
                <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 
                        x:Name="BarCodeTextBox"
                        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"
                        />
                    <CheckBox 
                        x:Name="IsGoodCheckBox" 
                        Grid.Column="4" 
                        IsEnabled="False" 
                        VerticalAlignment="Center"
                        >
                        <CheckBox.IsChecked>
                            <MultiBinding Converter="{StaticResource EqualityConverter}">
                                <Binding Path="BarCode" />
                                <Binding Path="Text" ElementName="BarCodeTextBox"/>
                            </MultiBinding>
                        </CheckBox.IsChecked>
                    </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>
    

    public class EqualityMultiConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            //  Return true if we have fewer than two values, 
            //  or if we have at least two, and they're all equal.
            return values.Length < 2 || values.Skip(1).All(v => values[0] == v);
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    
        3
  •  0
  •   Kacper Stachowski    7 年前

    您的代码每次都会找到相同的复选框,因为您是按名称定义的。相反,您应该按控件类型查找。

    根据来自的回答 another question ,你可以试试这样:

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }
    
                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
    }