由其他UserControl的ElementName触发

时间:2019-06-24 13:28:23

标签: c# wpf xaml

我有两个UserControls(A,B),并且我想从UserControl B中获得A_TextBox UserControl A中的错误。

 <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:Path =(0); DataItem = null;目标元素是'Button'(Name =''); target属性为“ NoTarget”(类型为“ Object”)

1 个答案:

答案 0 :(得分:1)

我已经创建了两个UserControl,A和B。A有一个文本框,其Text绑定到UserControl的integer属性,A还具有公共只读依赖项属性HasError。我收到一条错误消息,说Validation.HasError不能是数据绑定的,所以我要在文本更改的事件处理程序中手动更新该属性。我创建并包含了Integer属性,以便可以在文本框中键入“ xx”并使Validation.HasError为true。具有有效验证的所有内容都将相同。

在公共父级中,我通过布尔负值转换器将A.HasError绑定到B.IsEnabled。我也可以写一个像您一样的触发器。这种方法除了行之有效之外,其优点还在于,两个UserControl不必了解彼此的内部,并且两个都不依赖于另一个。另外,如果要在ListBox的ItemTemplate中创建这些对中的九对,则可以做到这一点而没有任何问题。

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