如何在没有名称属性的情况下在 C# 中获取具有相同父级的 WPF 的其他控件?

How to get the other control of WPF having same parent in c# without its name proprty?

我在 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 交换。

The purpose of this is to swap the Text of selected TextBlock with its adjacent TextBlock"

如我所料,你肯定做错了。

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

没有好的 Minimal, Complete, and Verifiable code example 就不可能提供任何关于您自己的代码的具体建议。但这是基本思想:

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

的实例

单击标记为 "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;
}