如何在c#中获得具有相同父对象的WPF的其他控件,而没有其名称属性

本文关键字:控件 其他 WPF 属性 对象 | 更新日期: 2023-09-27 18:08:35

我在XAML中有以下代码片段:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="01*"/>
        <ColumnDefinition Width="01*"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="1" Text="ABC" Name="txtBlockABC"/>
    <TextBlock Grid.Column="2" Text="DEF"/>
</Grid>

并且我想通过其他TextBlock(即txtBlockABC)的名称访问c#中的Text = "DEF"TextBlock

我试了以下方法。

TextBlock txtBlockDEF = (TextBlock) ((Grid) (txtBlock1stPlane.Parent)).Children[1];

但是它是用索引来访问的,而不是用Text属性。

我想要一些像Lamba Expression。如:

TextBlock txtBlockDEF = (List<TextBlock>) ((Grid) (txtBlock1stPlane.Parent)).Children.All().Where(x => x.Text = "DEF").ToList()[0];

更新:

这样做的目的是将所选TextBlockText与相邻的TextBlock交换。

如何在c#中获得具有相同父对象的WPF的其他控件,而没有其名称属性

这样做的目的是将选定的TextBlock的Text与相邻的TextBlock"

交换

正如我所怀疑的,你绝对做错了。

应该有一个视图模型。视图模型应该有两个属性,表示两个TextBlock元素显示的文本。每个元素都应该将它们的Text属性绑定到适当的视图模型属性。然后,当您想要交换值时,您只需在视图模型(您可以直接访问)上交换值。

如果没有一个好的最小化、完整和可验证的代码示例,就不可能提供任何关于您自己的代码的具体建议。但基本思想是:

class MyViewModel : INotifyPropertyChanged
{
    private string _text1;
    private string _text2;
    public string Text1
    {
        get { return _text1; }
        set { _UpdateField(ref _text1, value); }
    }
    public string Text2
    {
        get { return _text2; }
        set { _UpdateField(ref _text2, value); }
    }
    public ICommand SwapValues { get; }
    public MyViewModel()
    {
        SwapValues = new SwapValuesCommand(this);
    }
    private class SwapValuesComand : ICommand
    {
        private readonly MyViewModel _owner;
        public SwapValuesCommand(MyViewModel owner)
        {
            _owner = owner;
        }
        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) { return true; }
        public void Execute(object parameter)
        {
            string temp = _owner.Text1;
            _owner.Text1 = _owner.Text2;
            _owner.Text2 = temp;
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void _UpdateField<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
    {
        if (!EqualityComparer<T>.Default.Equals(field, newValue))
        {
            field = newValue;
            PropertyChanged?.DynamicInvoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

然后在XAML中,像这样:

<Button Content="Swap Values" Command="{Binding SwapValues}"/>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="01*"/>
        <ColumnDefinition Width="01*"/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="1" Text="{Binding Text1}" Name="txtBlockABC"/>
    <TextBlock Grid.Column="2" Text="{Binding Text2}"/>
</Grid>

上面所有XAML的DataContextMyViewModel类的一个实例。

单击标签为"Swap Values"的按钮将执行SwapValuesCommand.Execute()方法,该方法将交换值。UI元素的属性会自动更新。

我在这里展示了使用ICommand来执行交换,当然你可以将它连接到任何你想要的逻辑。

注意:上面的内容都是直接在浏览器中输入的。我甚至没有编译它,更不用说测试它或检查它的拼写错误,等等。这只是为了说明。我相信你可以使用它和其他WPF/MVVM示例来理解这里使用的基本设计概念,并调整程序的设计,使其按预期的方式工作。


当然,如果所有这些都失败了,我想你可以继续给TextBlock起一个名字。然后你可以直接访问它。这是一个不明智的方法,但它肯定是一个更好的选择,而不是试图导航视觉树,寻找TextBlock,并希望你找到正确的。

private void Button_Click(object sender, RoutedEventArgs e)
{
    TextBlock t = ((Grid)LogicalTreeHelper.GetParent(txtBlockABC))
                  .Children.OfType<TextBlock>()
                  .FirstOrDefault((tb) => { return tb.Text == "DEF"; });
    string dummy = txtBlockABC.Text;
    txtBlockABC.Text = t.Text;
    t.Text = dummy;
}