Запуск по ElementName из другого UserControl - PullRequest
0 голосов
/ 24 июня 2019

У меня есть два UserControls (A, B), и я хочу получить A_TextBox Ошибки в UserControl A от UserControl B. Возможно ли это?

 <Usercontrol x:Class="A" (...)>
     <TextBox x:name="A_TextBox (...)/>
 </Usercontrol>


<Usercontrol x:Class="B" (...)>
(...)
   <Controls:A/>

   <Button (...)>
      <Button.Style>
          <Style>
             <Style.Triggers>        
                <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=A_TextBox }" value="True">
                  <Setter Property="IsEnabled" Value="False" /> 
                </DataTrigger>
              </Style.Triggers>

Этот код вызывает ошибку:

System.Windows.Data Ошибка: 4: не удается найти источник для привязки со ссылкой «ElementName = A_TextBox». BindingExpression: Путь = (0); DataItem = NULL; Целевым элементом является «Кнопка» (Имя = ''); Свойство target - «NoTarget» (тип «Объект»)

1 Ответ

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

Я создал два элемента UserControl, A и B. A имеет текстовое поле, текст которого привязан к целочисленному свойству UserControl, а A также имеет общедоступное свойство зависимости только для чтения HasError. Я получаю сообщение об ошибке, говорящее, что Validation.HasError не может быть привязан к данным, поэтому я обновляю это свойство вручную в обработчике событий с измененным текстом. Я создал и включил свойство Integer, чтобы я мог ввести «xx» в текстовое поле и сделать Validation.HasError истинным. Все с рабочей проверкой будет работать так же.

В общем родителе я связываю A.HasError с B.IsEnabled через преобразователь логического отрицания. Я мог бы написать триггер, как и ваш Преимущество этого подхода, в дополнение к тому, что он работает, состоит в том, что двум элементам управления UserControl не нужно знать о внутренностях друг друга, и ни один из них не зависит от другого. Кроме того, если вы хотите создать девять из этих пар в ItemTemplate ListBox, вы можете сделать это без каких-либо проблем.

A.xaml

<TextBox 
    VerticalAlignment="Top"
    TextChanged="IntegerTextBox_TextChanged"
    Text="{Binding Integer, RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged}"
    />

A.xaml.cs

private void IntegerTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    HasError = Validation.GetHasError(sender as TextBox);
}

public bool HasError
{
    get { return (bool)GetValue(HasErrorProperty); }
    protected set { SetValue(HasErrorPropertyKey, value); }
}

internal static readonly DependencyPropertyKey HasErrorPropertyKey =
    DependencyProperty.RegisterReadOnly(nameof(HasError), typeof(bool), typeof(A),
        new PropertyMetadata(false));

public static readonly DependencyProperty HasErrorProperty = 
    HasErrorPropertyKey.DependencyProperty;

public int Integer
{
    get { return (int)GetValue(IntegerProperty); }
    set { SetValue(IntegerProperty, value); }
}

public static readonly DependencyProperty IntegerProperty =
    DependencyProperty.Register(nameof(Integer), typeof(int), typeof(A),
        new PropertyMetadata(0));

MainWindow.xaml

<Window.Resources>
    <local:NotConverter x:Key="Not" />
</Window.Resources>
<Grid>
    <StackPanel>
        <local:A 
            Integer="34" 
            x:Name="MyAInstance" 
            />
        <local:B
            IsEnabled="{Binding HasError, ElementName=MyAInstance, 
                        Converter={StaticResource Not}}"
            />
    </StackPanel>
</Grid>

MainWindow.xaml.cs

public class NotConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return !System.Convert.ToBoolean(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return !System.Convert.ToBoolean(value);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...