GetTemplateChild(" CompactOverlayButton")当Button返回Null

时间:2017-04-18 16:28:22

标签: c# xaml uwp win-universal-app

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

我希望对我创建的自定义Button有一个Visibility控件。所以我为它创建了一个属性。在该属性中,我使用GetTemplateChild("CompactOverlayButton") as Button来获取特定按钮,但它返回null。

这是我的代码

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

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

以下是OnApplyTemplate()

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

1 个答案:

答案 0 :(得分:0)

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

如果某些内容在应用模板之前设置了这个值,例如,如果它是可以在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