Конвертер не преобразует обратно в Textbox, не фокусируется внутри пользовательского элемента управления с двухсторонней привязкой к текстовому свойству - PullRequest
0 голосов
/ 22 февраля 2020

Я создаю пользовательский пользовательский элемент управления UWP. Я два способа связать текст в TextBox с IValueConverter, чтобы преобразовать строку в десятичную и обратно. Мой конвертер преобразует десятичную строку в текстовое поле при загрузке данных сзади. Однако я не могу запустить метод ConvertBack моего конвертера, когда Textbox теряет фокус внутри моего пользовательского элемента управления, как обычное поведение обычного элемента управления Textbox.

Есть ли способ заметить, что TextBox не сфокусирован и вызвать преобразование обратно к десятичному числу внутри моего usercontrol обратно к моим данным модели, хотя его свойство зависимости?

Вот мой 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>

Вот его код позади

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));
    }
}

Вот мой 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;
        }
    }
}


Это моя реализация 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>

1 Ответ

1 голос
/ 24 февраля 2020

Есть ли способ заметить расфокусировку TextBox и инициировать преобразование обратно в десятичное число в моем пользовательском контроле обратно в данные модели через его свойство зависимости?

Вы можете подписаться на событие LostFocus для прослушивания, если TextBox не сфокусирован. Затем в событии LostFocus вы можете передать текущее значение текстового поля своему свойству зависимостей Text, когда значение свойства Text изменится, он вызовет метод обратного преобразования и затем вернет десятичное число в данные модели.

В вашем 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"/>

В вашем usercontrol.cs:

......

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

или непосредственно установите модель привязки вашего текстового поля как Twoway.

В вашем 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}"/>
...