简体   繁体   English

转换器不转换回文本框,在自定义用户控件中不聚焦,通过两种方式绑定到文本属性

[英]Converter not converting back on Textbox unfocus inside custom user control with two way binding to text property

I am creating a custom UWP user control.我正在创建自定义 UWP 用户控件。 I am two way binding the text in a TextBox with an IValueConverter to convert a string to decimal and back.我通过两种方式将 TextBox 中的文本与 IValueConverter 绑定以将字符串转换为十进制并返回。 My converter is converting the decimal to a string in the Textbox when loading the data from behind.从后面加载数据时,我的转换器将小数点转换为文本框中的字符串。 However, I am unable to trigger my converter's ConvertBack method when the Textbox loses focus inside my custom control like the usual behavior of a regular Textbox control.但是,当文本框在自定义控件内失去焦点时,我无法触发转换器的 ConvertBack 方法,就像常规文本框控件的通常行为一样。

Is there a way to notice the TextBox unfocus and trigger the conversion back to the decimal inside my usercontrol back to my model data though its dependency property ?有没有办法注意到 TextBox 未聚焦并触发转换回我的用户控件中的小数点,通过其依赖属性返回我的模型数据?

Here is my UserControl.这是我的用户控件。

<UserControl
    <Grid Margin="15,0,15,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="5*"/>
            <ColumnDefinition Width="5*"/>
        </Grid.ColumnDefinitions>
        <TextBox
            x:Name="textBox"
            Grid.Row="0"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            Header="{x:Bind Header}"
            Text="{x:Bind Text}"
            IsEnabled="{x:Bind IsControlEnabled}"/>

        <TextBlock
            Grid.Row="1" 
            Grid.Column="0" 
            Foreground="RosyBrown"
            Text="{x:Bind InspectionValidation}"/>
    </Grid>
</UserControl>

Here is it's code-behind这是代码隐藏

public sealed partial class FrmTextBox : UserControl, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(string),
            typeof(FrmComboBox), new PropertyMetadata(null));

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string),
            typeof(FrmComboBox), new PropertyMetadata(null));

    public static readonly DependencyProperty
        InspectionValidationProperty =
            DependencyProperty.Register("InspectionValidation", typeof(string)
                , typeof(FrmInspection), null);

    public static readonly DependencyProperty
        IsLayoutEnabledProperty =
            DependencyProperty.Register("IsLayoutEnabled", typeof(int?)
                , typeof(FrmInspection), null);


    public string Header
    {
        get { return (string)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set
        {
            SetValue(TextProperty, value);
        }
    }

    public string InspectionValidation
    {
        get => (string) GetValue(InspectionValidationProperty);
        set =>SetValue( InspectionValidationProperty, value);
    }

    public int? IsLayoutEnabled
    {
        get => (int?) GetValue(IsLayoutEnabledProperty);
        set
        {
            IsControlEnabled = (value == -1) ? true : false;
            SetValue( IsLayoutEnabledProperty, value);
        }
    }
    private bool isControlEnabled { get; set; }
    public bool IsControlEnabled
    {
        get => isControlEnabled;
        set
        {
            if (value == isControlEnabled) return;
            isControlEnabled = value;
            OnPropertyChanged();

        }
    }

    public FrmTextBox()
    {
        this.InitializeComponent();
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Here is my IValueConverter这是我的 IValueConverter

public class StringToDecimalConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value != null)
            return value.ToString();

        return string.Empty;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        try
        {
            if (value != null)
            {
                Decimal newValue;
                Decimal.TryParse((string) value, out newValue);
                return newValue;
            }
            return null;
        }
        catch
        {
            return null;
        }
    }
}


This is my Xaml implementation of the user control.这是我的用户控件的 Xaml 实现。

<controls:FrmTextBox
   Grid.Row="1"
   Grid.Column="1"
   Header="Labor Count"
   Text="{x:Bind ViewModel.Current.LaborCount, Mode=TwoWay, Converter={StaticResource StringToDecimal}}"
   InspectionValidation=""
   IsLayoutEnabled="-1">
</controls:FrmTextBox>

Is there a way to notice the TextBox unfocus and trigger the conversion back to the decimal inside my usercontrol back to my model data though its dependency property ?有没有办法注意到 TextBox 未聚焦并触发转换回我的用户控件中的小数点,通过其依赖属性返回我的模型数据?

You can subscribe the LostFocus event to listen if the TextBox is unfocus.如果 TextBox 未聚焦,您可以订阅 LostFocus 事件以进行侦听。 Then in the LostFocus event, you can pass the current value of textbox to your Text dependency property, when the value of Text property changes, it will trigger the conversion back method and then back the decimal to your model data.然后在 LostFocus 事件中,您可以将 textbox 的当前值传递给您的 Text 依赖属性,当 Text 属性的值发生变化时,它将触发转换返回方法,然后将小数返回到您的模型数据中。

In your usercontrol.xaml:在您的 usercontrol.xaml 中:

<TextBox
        x:Name="textBox"
        Grid.Row="0"
        Grid.Column="0"
        Grid.ColumnSpan="2"
        Header="{x:Bind Header}"
        Text="{x:Bind Text}"
        IsEnabled="{x:Bind IsControlEnabled}" LostFocus="textBox_LostFocus"/>

In your usercontrol.cs:在您的 usercontrol.cs 中:

......

private void textBox_LostFocus(object sender, RoutedEventArgs e)
{
    Text = textBox.Text;
}

Or directly set the binding model of your textbox as Twoway.或者直接将你的文本框的绑定模型设置为 Twoway。

In your usercontrol.xaml:在您的 usercontrol.xaml 中:

<TextBox
        x:Name="textBox"
        Grid.Row="0"
        Grid.Column="0"
        Grid.ColumnSpan="2"
        Header="{x:Bind Header}"
        Text="{x:Bind Text,Mode=TwoWay}"
        IsEnabled="{x:Bind IsControlEnabled}"/>

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

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