简体   繁体   English

如何根据提供要绑定到的属性名称的字符串属性绑定TextBox.Text?

[英]How to bind TextBox.Text according to a string property that provides the name of the property I want to bind to?

Quite junior to WPF :) 初级到WPF :)

Context 语境

I have a Window with a DataContext containing a few ints. 我有一个带有包含几个整数的DataContext的窗口。 My window is basically just used to display "Key : Value" for each int, Value being an editable TextBox. 我的窗口基本上只用于显示每个int的“键:值”,值是可编辑的文本框。

As I edited my window to provide ValueConverters and ValidationRules, it appeared to me that I could use some generic classes, as they all have the same rules / converters. 当我编辑窗口以提供ValueConverters和ValidationRules时,在我看来我可以使用一些通用类,因为它们都具有相同的规则/转换器。

Problem 问题

Let's say I have int property_a, int property_b, int property_c; 假设我有int property_a,int property_b,int property_c; in my DataContext. 在我的DataContext中。 I have no idea on how to bind the content of the TextBox inside the generic class to those properties :/ 我不知道如何将通用类内部的TextBox的内容绑定到那些属性:/

I wanted to provide a string property like "property_a" to my generic class, but I then couldn't find how to make a dynamic binding using this property. 我想为我的通用类提供一个字符串属性,例如“ property_a”,但是后来我找不到使用该属性进行动态绑定的方法。

Code Samples 代码样例

  • My customized TextBox wrapper : 我的自定义TextBox包装器:
<Grid>
        <TextBox x:Name="IntBox" Grid.Row="1" Grid.Column="1" Margin="0, 5, 10, 5"
                 Style="{StaticResource TextBoxInError}">
            <TextBox.Text>
                <Binding Path="{no idea what to put here }">
                    <Binding.ValidationRules>
                        <validation:IntRule />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
    </Grid>
public partial class IntTextBox : UserControl
    {
        public string PropertyToBind { get; set; }

        public IntTextBox()
        {
            InitializeComponent();
        }
    }
  • The spot where I use my TextBox wrapper in my Window : 在Window中使用TextBox包装器的位置:
<input:IntTextBox x:Name="InitiativeBox" Grid.Row="1" Grid.Column="1" Margin="0, 5, 10, PropertyToBind="Initiative"/>

Thanks for your reading :) 感谢您的阅读:)

The short answer to your question is: You put the name of the public property which is in your datacontext. 这个问题的简短答案是:您将公共属性的名称放在数据上下文中。

I'm not sure that's a totally helpful answer though. 我不确定这是否是完全有用的答案。

You might find this sample thought provoking: 您可能会发现此示例令人发指:

https://social.technet.microsoft.com/wiki/contents/articles/29777.wpf-property-list-editing.aspx https://social.technet.microsoft.com/wiki/contents/articles/29777.wpf-property-list-editing.aspx

Maybe you should take a look at some super simple stuff first though: 也许您应该首先看一些超级简单的东西:

https://social.technet.microsoft.com/wiki/contents/articles/31915.wpf-mvvm-step-by-step-1.aspx https://social.technet.microsoft.com/wiki/contents/articles/31915.wpf-mvvm-step-by-step-1.aspx

https://social.technet.microsoft.com/wiki/contents/articles/32164.wpf-mvvm-step-by-step-2.aspx https://social.technet.microsoft.com/wiki/contents/articles/32164.wpf-mvvm-step-by-step-2.aspx

You'll be creating the binding in code behind. 您将在后面的代码中创建绑定。 PropertyToBind should be a dependency property, since it's a property of a UI element and you may want to bind it. PropertyToBind应该是依赖项属性,因为它是UI元素的属性,您可能需要绑定它。 We'll also rename it to PropertyPath , because that's consistent with how similar properties such as ListBox.SelectedValuePath are named in the WPF framework. 我们还将其重命名为PropertyPath ,因为这与WPF框架中类似属性ListBox.SelectedValuePath的命名方式一致。

Here's the XAML. 这是XAML。 Grid.Row and Grid.Column index from 0, not 1. You don't need them anyway, because you didn't define any rows or columns in your Grid (if this is a partial example and you simply omitted the row/column definitions, disregard those remarks). Grid.Row和Grid.Column的索引从0开始,而不是从1开始。您仍然不需要它们,因为您没有在Grid中定义任何行或列(如果这是部分示例,并且您只是省略了行/列定义,请忽略这些说明)。

<Grid>
    <TextBox 
        x:Name="IntBox" 
        Margin="0, 5, 10, 5"
        Style="{StaticResource TextBoxInError}"
        />
</Grid>

Code behind: 后面的代码:

public partial class IntTextBox : UserControl
{
    public IntTextBox()
    {
        InitializeComponent();
    }

    public String PropertyPath
    {
        get { return (String)GetValue(PropertyPathProperty); }
        set { SetValue(PropertyPathProperty, value); }
    }

    public static readonly DependencyProperty PropertyPathProperty =
        DependencyProperty.Register(nameof(PropertyPath), typeof(String), 
            typeof(IntTextBox),
            new FrameworkPropertyMetadata(PropertyPath_PropertyChanged));

    protected static void PropertyPath_PropertyChanged(DependencyObject d, 
        DependencyPropertyChangedEventArgs e)
    {
        var ctl = d as IntTextBox;

        var binding = new Binding(ctl.PropertyPath)
        {
            ValidationRules = { new IntRule() },

            //  Optional. With this, the bound property will be updated and validation 
            //  will be applied on every keystroke. Fine for integers. For doubles 
            //  or phone numbers, it'll drive your users up the wall. 
            UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
        };

        ctl.IntBox.SetBinding(TextBox.TextProperty, binding);
    }
}

I'm not sure what you're doing here is necessarily a good idea in this particular case, but the technique is respectable and that's how you do it. 在这种特殊情况下,我不确定您在此处执行的操作是否一定是个好主意,但是该技术是否值得尊重,这就是您的操作方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM