Пользовательский элемент управления wpf не показывает ошибку проверки - PullRequest
0 голосов
/ 29 декабря 2018

Ошибка проверки не будет отображаться, если я перенесу Binding через свойство Dependency в пользовательский элемент управления.

DETAIL

У меня есть модель просмотра, в которой всегда есть ошибка проверки на одномсвойство

class ViewModel : IDataErrorInfo
{
    public string Value { get; set; }

    public string Error
    {
        get { return null; }
    }

    public string this[string columnName]
    {
        get { return "Error"; }
    }
}

и TextBox в поле зрения

<TextBox 
    Text="{Binding Value, 
        Mode=TwoWay, 
        UpdateSourceTrigger=PropertyChanged, 
        ValidatesOnDataErrors=True, 
        NotifyOnValidationError=True}" />

, поэтому оно будет окружено красной рамкой.

ui picture

Затем я создал пользовательский элемент управления с именем WrappedTextBox, который содержит Text Свойство зависимости

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

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(
            "Text",
            typeof(string),
            typeof(WrappedTextBox));
}

и шаблон

<Style TargetType="local:WrappedTextBox">
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:WrappedTextBox">
                <Grid>
                    <AdornerDecorator>
                        <TextBox
                            Text="{Binding Text, 
                                Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged, 
                                ValidatesOnDataErrors=True, 
                                NotifyOnValidationError=True, 
                                RelativeSource={RelativeSource Mode=TemplatedParent}}" />
                    </AdornerDecorator>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

для отображения

<local:WrappedTextBox
    Text="{Binding Value, 
        Mode=TwoWay, 
        UpdateSourceTrigger=PropertyChanged, 
        ValidatesOnDataErrors=True, 
        NotifyOnValidationError=True}" />

, как показано на рисунке выше, второй элемент управления не имеет красной границы.

, если я не уберу Validation.ErrorTemplate из WrappedTextBox, это будет

picture 2

Как отобразить шаблон ошибки на TextBox внутри WrappedTextBox?

1 Ответ

0 голосов
/ 30 декабря 2018

Насколько я знаю, ваша проблема в том, что IDataErrorInfo должен быть реализован в классе, к которому вы привязаны, в вашем ControlTemplate вы привязываетесь к Text -Свойству вашего WrappedTextBox, следовательно, ваш* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * 101 '' '.*

Для того, что вы хотите достичь, мне пришло в голову 2 варианта ( Примечание : эти параметры создаются при условии, что вы делаете больше вещей, поэтому параметры ранее упомянутой статьи не применяются кВы)

Вариант 1 : Производный напрямую от TextBox

Код сзади:

class WrappedTextBox : TextBox
{

}

Стиль:

<Style TargetType="local:WrappedTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <AdornerDecorator>
                    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                        <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                    </Border>
                </AdornerDecorator>
                <-- ControlTemplate.Triggers etc. -->
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Использование: (как и прежде)

<local:WrappedTextBox
    Text="{Binding Value, 
        Mode=TwoWay, 
        UpdateSourceTrigger=PropertyChanged, 
        ValidatesOnDataErrors=True, 
        NotifyOnValidationError=True}" />

Опция 2 : передать Binding сам

Код позади:

[TemplatePart(Name = "PART_TEXTBOX", Type = typeof(TextBox))]
class WrappedTextBox : Control
{
    private TextBox _partTextBox;

    private BindingBase _textBinding;
    public BindingBase TextBinding
    {
        get => _textBinding;
        set
        {
            if (_textBinding != value)
            {
                _textBinding = value;
                ApplyTextBinding();
            }
        }
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        _partTextBox = base.GetTemplateChild("PART_TEXTBOX") as TextBox;
        ApplyTextBinding();
    }

    private void ApplyTextBinding()
    {
        if (_partTextBox != null)
            BindingOperations.SetBinding(_partTextBox, TextBox.TextProperty, _textBinding);
    }
}

Стиль:

<Style TargetType="local:WrappedTextBox">
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:WrappedTextBox">
                <Grid>
                    <AdornerDecorator>
                        <TextBox x:Name="PART_TEXTBOX" />
                    </AdornerDecorator>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Использование:

<local:WrappedTextBox
    TextBinding="{Binding Value, 
        Mode=TwoWay, 
        UpdateSourceTrigger=PropertyChanged, 
        ValidatesOnDataErrors=True, 
        NotifyOnValidationError=True}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...