Почему не работает моя привязка для параметра правила проверки TextBox? - PullRequest
0 голосов
/ 06 июня 2019

У меня есть пользовательский элемент управления с TextBox, который должен быть проверен. Проверка будет варьироваться в зависимости от значения свойства зависимости в UC, поэтому мне нужно передать это как параметр. Для передачи параметра я использую Передача привязанного к данным значения правилу проверки в качестве руководства. Тем не менее, привязка, которую я использую, не работает, и я не знаю почему. Я ударился головой об этом, погуглил все, что могу придумать, без радости.

Вот код. Надеюсь, я предоставил достаточно ...

В пользовательском контроле у ​​меня есть этот XAML.

    <TextBox Name="ValueBox" 
            PreviewMouseLeftButtonUp="OnPreviewMouseLeftButtonUp" 
            Height="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Height}"
            BorderThickness="0"
            TextAlignment="Center" 
            VerticalContentAlignment="Center">
        <TextBox.Style>
            <Style TargetType="TextBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=IsControlEnabled}"
                                 Value="False">
                        <Setter Property="Background" Value="{StaticResource DisabledColor}"/>
                    </DataTrigger>

                    <DataTrigger 
                                 Binding="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=InteractionMode}"
                                 Value="{x:Static local:TreatmentScheduleNumberBoxUserControl+InteractionModes.Select}">
                        <Setter Property="IsReadOnly" Value="True" />
                        <Setter Property="Cursor" Value="{x:Static Cursors.Hand}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
        <TextBox.Resources>
            <local:NumberBoxValueConverter x:Key="NumberBoxConverter"/>
        </TextBox.Resources>
        <TextBox.Text>
            <tools:ConverterBindableParameter
                Converter="{StaticResource NumberBoxConverter}"
                ConverterParameterBinding="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=TreatmentLampType}">
                <!--https://social.technet.microsoft.com/wiki/contents/articles/31422.wpf-passing-a-data-bound-value-to-a-validation-rule.aspx-->
                <tools:ConverterBindableParameter.Binding>
                    <Binding RelativeSource="{RelativeSource AncestorType=UserControl}" Path="Value" FallbackValue="3">
                        <Binding.ValidationRules>
                            <local:NumberBoxValidationRule>
                                <local:NumberBoxValidationRule.Wrapper>
                                    <local:Wrapper NumberBoxUsage1="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=NumberBoxUsage
                                        , Converter={StaticResource DebugDummyConverter, PresentationTraceSources.TraceLevel=High}}" />
                                </local:NumberBoxValidationRule.Wrapper>
                            </local:NumberBoxValidationRule>
                        </Binding.ValidationRules>
                    </Binding>
                </tools:ConverterBindableParameter.Binding>
            </tools:ConverterBindableParameter>
        </TextBox.Text>
    </TextBox>

Проблема заключается в этой привязке, где NumberBoxUsage1 - это свойство зависимости в среде проверки, а NumberBoxUsage - это свойство зависимости в UC.

<local:Wrapper NumberBoxUsage1="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=NumberBoxUsage
, Converter={StaticResource DebugDummyConverter, PresentationTraceSources.TraceLevel=High}}" />

При запуске NumberBoxUsage1 остается по умолчанию и ему не присваивается значение NumberBoxUsage. Я могу изменить привязку к буквальному назначению, и это работает. Я добавил фиктивный конвертер, как показано, а также PresentationTraceSources, но конвертер никогда не вызывается, и в окне вывода нет трассировки. Любая помощь приветствуется.

Могу добавить, что все остальное в этом TextBox работает нормально. Вот соответствующий материал C #.

Упаковочный

   public class Wrapper : DependencyObject
    {
        public NumberBoxUsages NumberBoxUsage1 {
            get => (NumberBoxUsages)GetValue(NumberBoxUsage1Property);
            set => SetValue(NumberBoxUsage1Property, value);
        }

        public static readonly DependencyProperty NumberBoxUsage1Property =
            DependencyProperty.Register(nameof(NumberBoxUsage1), typeof(NumberBoxUsages), typeof(Wrapper),
                new FrameworkPropertyMetadata(
                    NumberBoxUsages.UvPrim,
                    (sender, e) =>
                    {
                        var dObj = sender as Wrapper;
                        var x = dObj.NumberBoxUsage1;
                        // leave for debugging help
                    }
                ));
    }

NumberBoxValidationRule

public class NumberBoxValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (value == null)
        {
            return new ValidationResult(false, "Please enter a value");
        }

        if (Wrapper.NumberBoxUsage1 == NumberBoxUsages.UvbPriPct)
        {

        }

        return ValidationResult.ValidResult;
    }

    public Wrapper Wrapper { get; set; }
}

ConverterBindableParameter

public class ConverterBindableParameter : MarkupExtension
{
    #region Public Properties

    public Binding Binding { get; set; }

    public IValueConverter Converter { get; set; }

    public Binding ConverterParameterBinding { get; set; }

    #endregion

    #region Overridden Methods

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var multiBinding = new MultiBinding();
        multiBinding.Bindings.Add(Binding);
        multiBinding.Bindings.Add(ConverterParameterBinding);
        var adapter = new MultiValueConverterAdapter
        {
            Converter = Converter
        };
        multiBinding.Converter = adapter;
        return multiBinding.ProvideValue(serviceProvider);
    }

    [ContentProperty("Converter")]
    public class MultiValueConverterAdapter : IMultiValueConverter
    {
        public IValueConverter Converter { get; set; }

        private object lastParameter;

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (Converter == null) return values[0]; // Required for VS design-time
            if (values.Length > 1) lastParameter = values[1];
            return Converter.Convert(values[0], targetType, lastParameter, culture);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            if (Converter == null) return new object[] { value }; // Required for VS design-time

            return new object[] { Converter.ConvertBack(value, targetTypes[0], lastParameter, culture) };
        }
    }

    #endregion
}

1 Ответ

1 голос
/ 07 июня 2019

Вам не хватает BindingProxy, которое захватывает DataContext:

public class BindingProxy : System.Windows.Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
}

XAML:

<TextBox.Resources>
    <local:NumberBoxValueConverter x:Key="NumberBoxConverter"/>
    <local:BindingProxy x:Key="proxy" Data="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</TextBox.Resources>
...
<local:Wrapper NumberBoxUsage1="{Binding Source={StaticResource proxy}, Path=Data.NumberBoxUsage, 
    Converter={StaticResource DebugDummyConverter}}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...