从子元素调用parent的方法

时间:2017-12-12 09:47:52

标签: c# wpf parents

在以下结构中

<Border ...>
    <ItemsControl>
        <ItemsControl.Template>
            <DataTemplate>
                <ACustomElement>
                    <Border MouseLeftButtonDown="method1">
                </ACustomElement>
            </DataTemplate>
        </ItemsControl.Template>
    </ItemsControl>
</Border>

我想从method1()内部调用ACustomElement类中的公共方法。

到目前为止我在method1()中尝试了什么:

var cr = ((Border)sender).Parent;
cr.method2();

method2是我的ACustomElement类中的公共方法。但它似乎没有认识到这种方法。

我收到以下错误:

  

'DependencyObject'不包含'method2'的定义,并且没有可以找到接受类型'DependencyObject'的第一个参数的扩展方法'method2'(你是否缺少using指令或汇编引用?)

有关如何解决此问题的任何建议? 当然,我只是错过演员或其他什么......

编辑:以下样式将始终应用于ACustomElement:

<Style TargetType="{x:Type c:ACustomElement}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type c:ACustomElement}">
                <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

3 个答案:

答案 0 :(得分:2)

您必须将cr转换为ACustomElement类型

var cr = (ACustomElement)((Border)sender).Parent;
cr.method2();

否则,您的cr变量引用了异常中所见的DependencyObject类型。

如果您不确定层次结构,请使用此方法查找特定类型的父级。

private T FindParent<T>(DependencyObject child) where T : DependencyObject {
    var parent = VisualTreeHelper.GetParent(child) as T;
    if (parent != null)
        return parent;
    return FindParent<T>(parent);
}

// usage
private void method1(object sender, MouseButtonEventArgs e)
{
    var cr = FindParent<ACustomElement>((Border)sender);
}

此外,DateTemplate可以是ItemsControl.ItemTemplate的子项,但不是ItemsControl.Template的子项(需要ControlTemplate)

 <ItemsControl.ItemTemplate>
      <DataTemplate>
          <local:ACustomElement>
              <Border MouseLeftButtonDown="method1" />
          </local:ACustomElement>
      </DataTemplate>
 </ItemsControl.ItemTemplate>

<强>更新

正如我在问题的评论中指出的那样,直接向您的类型添加事件处理程序或绑定命令。你为什么这么复杂?

答案 1 :(得分:0)

尝试将Tag的{​​{1}}属性绑定到自定义控件:

Border

...并在事件处理程序中强制转换<ACustomElement> <Border MouseLeftButtonDown="method1" Tag="{Binding RelativeSource={RelativeSource AncestorType=ACustomElement}}"> </ACustomElement> 属性:

Tag

答案 2 :(得分:-1)

ngRepeat

是安全和正确的。

正如您所怀疑的那样,您错过了演员阵容,但模式匹配方法比直接添加演员阵容更具可读性和弹性。

编译错误的原因是if (sender is Border b && b.Parent is ACustomElement c) { c.method2(); } 只是键入为表示父元素的常规类型,而不是您创建的自定义元素类的实例。