简体   繁体   中英

Labeled TextBox in Windows Universal App

I'm trying to realize a labeled TextBox in a windows universal app using C# and XAML , but I did not get the value of the TextBox in return, just empty string.

The code of my generic.xaml for it looks like this:

<Style TargetType="template:LabeledTextBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="template:LabeledTextBox">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <TextBlock Text="{TemplateBinding Label}" FontWeight="Bold" VerticalAlignment="Center" Margin="10,0" />
                    <TextBox Text="{TemplateBinding Value}" IsReadOnly="{TemplateBinding IsReadOnly}" VerticalAlignment="Center" Margin="20,0,10,0" Grid.Row="1" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The control looks like this:

public sealed class LabeledTextBox : Control, IParameterReturnable
{
    public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(LabeledTextBox), new PropertyMetadata(default(string)));
    public string Label
    {
        get { return this.GetValue(LabelProperty).ToString(); }
        set { this.SetValue(LabelProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(LabeledTextBox), new PropertyMetadata(default(string)));
    public string Value
    {
        get { return this.GetValue(ValueProperty).ToString(); }
        set { this.SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(LabeledTextBox), new PropertyMetadata(false));
    public string IsReadOnly
    {
        get { return this.GetValue(IsReadOnlyProperty).ToString(); }
        set { this.SetValue(IsReadOnlyProperty, value); }
    }

    public LabeledTextBox()
    {
        this.DefaultStyleKey = typeof(LabeledTextBox);
    }

    public LabeledTextBox(Parameter parameter)
    {
        this.Label = parameter.DisplayName;
        this.Value = parameter.DefaultValue ?? "";
        this.DefaultStyleKey = typeof(LabeledTextBox);
    }

    public string GetKey()
    {
        return this.Label;
    }

    public string GetValue()
    {
        return this.Value;
    }
}

You are free to ignore my IParameterReturnable , which I am using to access to GetKey() and GetValue() while looping through different types of these labeled-controls.

So what am I missing, what am I doing wrong?

Thank you very much for all helpful and well meant answers!

EDIT: Code for adding Control

The control is added dynamically with C# like this:

foreach (Parameter parameter in parameters)
{
    stackPanel.Children.Add(new LabeledTextBox(parameter));
}

But it would looks like this in Xaml:

<templates:LabeledTextBox Label="[Label]" Value="[Value]" IsReadOnly="False" />

It will be read out like this:

foreach(IParameterReturnable parameter in stackPanel.Children)
{
    string val = parameter.GetValue() // <= this will always return the default value
}

You are not updating the Value property with a new value from your templated TextBox .

In your generic.xaml add a name to your TextBox : <TextBox x:Name="PART_TextBox"...

Then your LabeledTextBox class should look like this:

[TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]
public sealed class LabeledTextBox : Control, IParameterReturnable
{
    public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(LabeledTextBox), new PropertyMetadata(default(string)));
    public string Label
    {
        get { return this.GetValue(LabelProperty).ToString(); }
        set { this.SetValue(LabelProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(LabeledTextBox), new PropertyMetadata(default(string)));
    public string Value
    {
        get { return this.GetValue(ValueProperty).ToString(); }
        set { this.SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(LabeledTextBox), new PropertyMetadata(false));
    public string IsReadOnly
    {
        get { return this.GetValue(IsReadOnlyProperty).ToString(); }
        set { this.SetValue(IsReadOnlyProperty, value); }
    }

    public LabeledTextBox()
    {
        this.DefaultStyleKey = typeof(LabeledTextBox);
    }

    private TextBox _textBox;

    protected override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        _textBox = GetTemplateChild("PART_TextBox") as TextBox;

        if (_textBox != null)
        {
            _textBox.TextChanged += TextBoxOnTextChanged;
        }
    }

    private void TextBoxOnTextChanged(object sender, TextChangedEventArgs textChangedEventArgs)
    {
        this.Value = _textBox.Text;
    }

    public LabeledTextBox(Parameter parameter)
    {
        this.Label = parameter.DisplayName;
        this.Value = parameter.DefaultValue ?? "";
        this.DefaultStyleKey = typeof(LabeledTextBox);
    }

    public string GetKey()
    {
        return this.Label;
    }

    public string GetValue()
    {
        return this.Value;
    }
}

Notice that I have added the TemplatePart attribute and overriden the OnApplyTemplate in which I register for the TextChanged event of the TextBox . When the text changes, I update the Value dependency property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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