GetTemplateChild("CompactOverlayButton") 作为按钮 returns Null

GetTemplateChild("CompactOverlayButton") as Button returns Null

我正在创建自定义传输控件。

我想为我创建的自定义按钮设置可见性控件。所以我为它创建了一个属性。在 属性 中,我使用 GetTemplateChild("CompactOverlayButton") as Button 来获取特定按钮,但它 returns 为空。

这是我的代码

public bool IsCompactOverlayButtonVisible
{
        get
        {
            var compactOverlayButton = GetTemplateChild("CompactOverlayButton") as Button;
            if (compactOverlayButton.Visibility == Visibility.Visible)
                return true;
            else
                return false;
        }
        set
        {
            var compactOverlayButton = GetTemplateChild("CompactOverlayButton") as Button;
            if (value)
                compactOverlayButton.Visibility = Visibility.Visible;
            else
                compactOverlayButton.Visibility = Visibility.Collapsed;
        }
}

但是同一行代码returns在OnApplyTemplate()函数中的正确值。

这是我的 OnApplyTemplate()

代码
protected override void OnApplyTemplate()
{
        var compactOverlayButton = GetTemplateChild("CompactOverlayButton") as Button;
        compactOverlayButton.Click += CompactOverlayButton_ClickAsync;
        base.OnApplyTemplate();
}

IsCompactOverlayButtonVisible 可能在 OnApplyTemplate() 之前第一次被求值,这意味着它第一次被求值时,模板还没有被应用,按钮还不存在。在 OnApplyTemplate() 中,获取按钮并将其分配给私有字段。

private Button _compactOverlayButton;
protected override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    _compactOverlayButton = GetTemplateChild("CompactOverlayButton") as Button;
    _compactOverlayButton.Click += CompactOverlayButton_ClickAsync;
}

在尝试触摸按钮的属性之前,请确保它不为空。

public bool IsCompactOverlayButtonVisible
{

    get
    {
        return _compactOverlayButton != null
            && _compactOverlayButton.Visibility == Visibility.Visible;
    }
    set
    {
        if (_compactOverlayButton != null)
        {
            compactOverlayButton.Visibility = value 
                                                ? Visibility.Visible
                                                : Visibility.Collapsed;
        }
    }
}

如果某些东西会在应用模板之前设置这个值,例如,如果它是一个 public 属性 控件,可以在 XAML 中设置(它确实看起来就像它一样),你不能这样做。您需要使其成为常规依赖项 属性,给它一个 PropertyChanged 处理程序来更新按钮的可见性 如果 按钮存在,并在 OnApplyTemplate() 当你拿到它时更新实际的按钮。然后它也可以用作绑定的目标。

更新

这是您的操作方法。这才是正确的方法。

private Button _compactOverlayButton;

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    _compactOverlayButton = GetTemplateChild("CompactOverlayButton") as Button;

    //  Update actual button visibility to match whatever the dependency property value 
    //  is, in case XAML gave us a value for it already. 
    OnIsCompactOverlayButtonVisibleChanged();

    _compactOverlayButton.Click += CompactOverlayButton_Click;

    //  Secondly, just in case something in the XAML may change the button's visibility, 
    //  put a watch on the property and update our dependency property to match when that 
    //  changes. 
    var dpd = DependencyPropertyDescriptor.FromProperty(Button.VisibilityProperty, typeof(Button));
    dpd.AddValueChanged(_compactOverlayButton, CompactOverlayButton_VisibilityChanged);
}

protected void CompactOverlayButton_VisibilityChanged(object sender, EventArgs args)
{
    IsCompactOverlayButtonVisible = _compactOverlayButton.Visibility == Visibility.Visible;
}

private void CompactOverlayButton_Click(object sender, RoutedEventArgs e)
{
    //  ...whatever
}

#region IsCompactOverlayButtonVisible Property
public bool IsCompactOverlayButtonVisible
{
    get { return (bool)GetValue(IsCompactOverlayButtonVisibleProperty); }
    set { SetValue(IsCompactOverlayButtonVisibleProperty, value); }
}

public static readonly DependencyProperty IsCompactOverlayButtonVisibleProperty =
    DependencyProperty.Register(nameof(IsCompactOverlayButtonVisible), typeof(bool), typeof(CustomMediaTransportControls),
        new FrameworkPropertyMetadata(true,
                                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                        IsCompactOverlayButtonVisible_PropertyChanged));

protected static void IsCompactOverlayButtonVisible_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    //  It's a hassle to do stuff in a static method, so my dependency property 
    //  snippet just creates a private instance method and calls it from the 
    //  static handler. 
    (d as CustomMediaTransportControls).OnIsCompactOverlayButtonVisibleChanged();
}

private void OnIsCompactOverlayButtonVisibleChanged()
{
    if (_compactOverlayButton != null)
    {
        //  If the existing value is the same as the new value, this is a no-op
        _compactOverlayButton.Visibility = 
            IsCompactOverlayButtonVisible
                ? Visibility.Visible
                : Visibility.Collapsed;
    }
}
#endregion IsCompactOverlayButtonVisible Property