У меня есть пользовательский элемент управления с 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
}