2013-03-02 74 views
0

我有以下CustomControl,我想作爲一個橫幅基本使用方法:在WinRT的XAML找不到元素

XAML:

<UserControl x:Name="userControl" 
    x:Class="Nova.WinRT.Controls.BannerPanel" 
    ...> 

    <Grid Background="#BF8B8B8B"> 
     <Grid Height="400" Background="#FF050A7C" VerticalAlignment="Center"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="50"/> 
       <RowDefinition Height="*"/> 
       <RowDefinition Height="50"/> 
      </Grid.RowDefinitions> 
      <TextBlock x:Name="_Title" Text="Title" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center"/> 
      <ContentPresenter x:Name="_Content" Grid.Row="1"/> 
      <StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Center"> 
       <Button x:Name="_OK" Content="OK" HorizontalAlignment="Center" Click="OkPressed" FontSize="18" Width="100" Margin="20,0" /> 
       <Button x:Name="_Cancel" Content="Cancel" HorizontalAlignment="Center" Click="CancelPressed" FontSize="18" Width="100" Margin="20,0" /> 
      </StackPanel> 
     </Grid> 
    </Grid> 
</UserControl> 

C#:

public sealed partial class BannerPanel : UserControl 
{ 
    /// <summary> 
    /// Title of the Banner 
    /// </summary> 
    public string Title 
    { 
     get { return _Title.Text; } 
     set { _Title.Text = value; } 
    } 

    /// <summary> 
    /// The visibility of the OK button 
    /// </summary> 
    public Visibility OKVisibility 
    { 
     get { return _OK.Visibility; } 
     set { _OK.Visibility = value; } 
    } 

    /// <summary> 
    /// The visibility of the Cancel button 
    /// </summary> 
    public Visibility CancelVisibility 
    { 
     get { return _Cancel.Visibility; } 
     set { _Cancel.Visibility = value; } 
    } 

    /// <summary> 
    /// The inner content of the panel 
    /// </summary> 
    public FrameworkElement InnerContent 
    { 
     get { return (FrameworkElement)_Content.Content; } 
     set { _Content.Content = value; } 
    } 

    /// <summary> 
    /// Fires when the Ok button is clicked 
    /// </summary> 
    public event RoutedEventHandler OkClick; 

    /// <summary> 
    /// Fires when the Cancel button is clicked 
    /// </summary> 
    public event RoutedEventHandler CancelClick; 
}; 

但是,當我用它(請參閱下面的XAML),自動生成的代碼沒有找到在內部內容的元素:

XA ML:

<Controls:BannerPanel x:Name="Banner" Title="Terms and Policy" CancelVisibility="Collapsed" OkClick="OnTermsAccepted"> 
    <Controls:BannerPanel.InnerContent> 
     <ScrollViewer Width="500"> 
      <TextBlock x:Name="TermsText" TextWrapping="Wrap" FontSize="12" /> 
     </ScrollViewer> 
    </Controls:BannerPanel.InnerContent> 
</Controls:BannerPanel> 

C#:

public sealed partial class TermsBanner : UserControl 
{ 
    /// <summary> 
    /// Constructor 
    /// </summary> 
    public TermsBanner() 
    { 
     this.InitializeComponent(); 

     // Why do I have to find TermsText Manually like this?????? 
     TermsText = (Banner.InnerContent as ScrollViewer).Content as TextBlock; 
     TermsText.Text = TermsOfUse; 
    } 
}; 

爲什麼我的變量TermsText手動指向正確的事?爲什麼不能像FindName()那樣自動找到它?

回答

4
  1. 您應該定義DependencyProperty屬性而不是常規屬性。
  2. ContentControl代替UserControl派生。
  3. 將在主題的XAML/Generic.xaml在Style/Setter/Property="Template" Value="...。如果使用模板控制VS項目模板創建控件,它會自動發生。
  4. 使用TemplateBinding將內部模板元素的屬性綁定到您的控件屬性。

FindName可能不跨越名稱範圍工作。我從不使用它。

藉口錯別字。打在手機上。

這裏有一個解決方案:

創建模板控制(又名我們自定義的控制 - 不要與用戶控件相混淆),並修改了它從ContentControl,而不是Control推導:

using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 

// The Templated Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234235 

namespace App124 
{ 
    [TemplatePart(Name = "_OK", Type = typeof(Button))] 
    [TemplatePart(Name = "_Cancel", Type = typeof(Button))] 
    public sealed class BannerPanel : ContentControl 
    { 
     #region Title 
     /// <summary> 
     /// Title Dependency Property 
     /// </summary> 
     public static readonly DependencyProperty TitleProperty = 
      DependencyProperty.Register(
       "Title", 
       typeof(string), 
       typeof(BannerPanel), 
       new PropertyMetadata(null, OnTitleChanged)); 

     /// <summary> 
     /// Gets or sets the Title property. This dependency property 
     /// indicates .... 
     /// </summary> 
     public string Title 
     { 
      get { return (string)GetValue(TitleProperty); } 
      set { SetValue(TitleProperty, value); } 
     } 

     /// <summary> 
     /// Handles changes to the Title property. 
     /// </summary> 
     /// <param name="d"> 
     /// The <see cref="DependencyObject"/> on which 
     /// the property has changed value. 
     /// </param> 
     /// <param name="e"> 
     /// Event data that is issued by any event that 
     /// tracks changes to the effective value of this property. 
     /// </param> 
     private static void OnTitleChanged(
      DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var target = (BannerPanel)d; 
      string oldTitle = (string)e.OldValue; 
      string newTitle = target.Title; 
      target.OnTitleChanged(oldTitle, newTitle); 
     } 

     /// <summary> 
     /// Provides derived classes an opportunity to handle changes 
     /// to the Title property. 
     /// </summary> 
     /// <param name="oldTitle">The old Title value</param> 
     /// <param name="newTitle">The new Title value</param> 
     private void OnTitleChanged(
      string oldTitle, string newTitle) 
     { 
     } 
     #endregion 

     #region OKVisibility 
     /// <summary> 
     /// OKVisibility Dependency Property 
     /// </summary> 
     public static readonly DependencyProperty OKVisibilityProperty = 
      DependencyProperty.Register(
       "OKVisibility", 
       typeof(Visibility), 
       typeof(BannerPanel), 
       new PropertyMetadata(Visibility.Visible, OnOKVisibilityChanged)); 

     /// <summary> 
     /// Gets or sets the OKVisibility property. This dependency property 
     /// indicates .... 
     /// </summary> 
     public Visibility OKVisibility 
     { 
      get { return (Visibility)GetValue(OKVisibilityProperty); } 
      set { SetValue(OKVisibilityProperty, value); } 
     } 

     /// <summary> 
     /// Handles changes to the OKVisibility property. 
     /// </summary> 
     /// <param name="d"> 
     /// The <see cref="DependencyObject"/> on which 
     /// the property has changed value. 
     /// </param> 
     /// <param name="e"> 
     /// Event data that is issued by any event that 
     /// tracks changes to the effective value of this property. 
     /// </param> 
     private static void OnOKVisibilityChanged(
      DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var target = (BannerPanel)d; 
      Visibility oldOKVisibility = (Visibility)e.OldValue; 
      Visibility newOKVisibility = target.OKVisibility; 
      target.OnOKVisibilityChanged(oldOKVisibility, newOKVisibility); 
     } 

     /// <summary> 
     /// Provides derived classes an opportunity to handle changes 
     /// to the OKVisibility property. 
     /// </summary> 
     /// <param name="oldOKVisibility">The old OKVisibility value</param> 
     /// <param name="newOKVisibility">The new OKVisibility value</param> 
     private void OnOKVisibilityChanged(
      Visibility oldOKVisibility, Visibility newOKVisibility) 
     { 
     } 
     #endregion 

     #region CancelVisibility 
     /// <summary> 
     /// CancelVisibility Dependency Property 
     /// </summary> 
     public static readonly DependencyProperty CancelVisibilityProperty = 
      DependencyProperty.Register(
       "CancelVisibility", 
       typeof(Visibility), 
       typeof(BannerPanel), 
       new PropertyMetadata(Visibility.Visible, OnCancelVisibilityChanged)); 

     /// <summary> 
     /// Gets or sets the CancelVisibility property. This dependency property 
     /// indicates .... 
     /// </summary> 
     public Visibility CancelVisibility 
     { 
      get { return (Visibility)GetValue(CancelVisibilityProperty); } 
      set { SetValue(CancelVisibilityProperty, value); } 
     } 

     /// <summary> 
     /// Handles changes to the CancelVisibility property. 
     /// </summary> 
     /// <param name="d"> 
     /// The <see cref="DependencyObject"/> on which 
     /// the property has changed value. 
     /// </param> 
     /// <param name="e"> 
     /// Event data that is issued by any event that 
     /// tracks changes to the effective value of this property. 
     /// </param> 
     private static void OnCancelVisibilityChanged(
      DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var target = (BannerPanel)d; 
      Visibility oldCancelVisibility = (Visibility)e.OldValue; 
      Visibility newCancelVisibility = target.CancelVisibility; 
      target.OnCancelVisibilityChanged(oldCancelVisibility, newCancelVisibility); 
     } 

     /// <summary> 
     /// Provides derived classes an opportunity to handle changes 
     /// to the CancelVisibility property. 
     /// </summary> 
     /// <param name="oldCancelVisibility">The old CancelVisibility value</param> 
     /// <param name="newCancelVisibility">The new CancelVisibility value</param> 
     private void OnCancelVisibilityChanged(
      Visibility oldCancelVisibility, Visibility newCancelVisibility) 
     { 
     } 
     #endregion 

     /// <summary> 
     /// Fires when the Ok button is clicked 
     /// </summary> 
     public event RoutedEventHandler OkClick; 

     /// <summary> 
     /// Fires when the Cancel button is clicked 
     /// </summary> 
     public event RoutedEventHandler CancelClick; 

     public BannerPanel() 
     { 
      this.DefaultStyleKey = typeof(BannerPanel); 
     } 

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

      var cancelButton = (Button)GetTemplateChild("_Cancel"); 
      var okButton = (Button)GetTemplateChild("_OK"); 
      cancelButton.Click += CancelClick; 
      okButton.Click += OkClick; 
     } 
    } 
} 

更新主題/ Generic.xaml這樣:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:App124"> 

    <Style 
     TargetType="local:BannerPanel"> 
     <Setter 
      Property="HorizontalContentAlignment" 
      Value="Left" /> 
     <Setter 
      Property="VerticalContentAlignment" 
      Value="Top" /> 
     <Setter 
      Property="Title" 
      Value="Title" /> 
     <Setter 
      Property="OKVisibility" 
      Value="Visible" /> 
     <Setter 
      Property="CancelVisibility" 
      Value="Visible" /> 
     <Setter 
      Property="Template"> 
      <Setter.Value> 
       <ControlTemplate 
        TargetType="local:BannerPanel"> 
        <Grid 
         Background="#BF8B8B8B"> 
         <Grid 
          Height="400" 
          Background="#FF050A7C" 
          VerticalAlignment="Center"> 
          <Grid.RowDefinitions> 
           <RowDefinition 
            Height="50" /> 
           <RowDefinition 
            Height="*" /> 
           <RowDefinition 
            Height="50" /> 
          </Grid.RowDefinitions> 
          <TextBlock 
           x:Name="_Title" 
           Text="{TemplateBinding Title}" 
           FontSize="30" 
           HorizontalAlignment="Center" 
           VerticalAlignment="Center" /> 
          <ContentPresenter 
           Grid.Row="1" 
           ContentTemplate="{TemplateBinding ContentTemplate}" 
           ContentTransitions="{TemplateBinding ContentTransitions}" 
           Content="{TemplateBinding Content}" 
           HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
           Margin="{TemplateBinding Padding}" 
           VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> 
          <StackPanel 
           Orientation="Horizontal" 
           Grid.Row="2" 
           HorizontalAlignment="Center"> 
           <Button 
            x:Name="_OK" 
            Content="OK" 
            Visibility="{TemplateBinding OKVisibility}" 
            HorizontalAlignment="Center" 
            FontSize="18" 
            Width="100" 
            Margin="20,0" /> 
           <Button 
            x:Name="_Cancel" 
            Content="Cancel" 
            Visibility="{TemplateBinding CancelVisibility}" 
            HorizontalAlignment="Center" 
            FontSize="18" 
            Width="100" 
            Margin="20,0" /> 
          </StackPanel> 
         </Grid> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

這是它是如何在MainPage.xaml中使用:背後

<Page 
    x:Class="App124.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:App124" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d"> 
    <Grid 
     Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 
     <local:BannerPanel 
      x:Name="Banner" 
      Title="Terms and Policy" 
      CancelVisibility="Collapsed" 
      OkClick="OnTermsAccepted"> 
      <ScrollViewer 
       Width="500"> 
       <TextBlock 
        x:Name="TermsText" 
        Text="Terms and Conditions" 
        TextWrapping="Wrap" 
        FontSize="12" /> 
      </ScrollViewer> 
     </local:BannerPanel> 
    </Grid> 
</Page> 

MainPage.xaml.cs中的代碼:

using Windows.UI.Popups; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 

namespace App124 
{ 
    /// <summary> 
    /// An empty page that can be used on its own or navigated to within a Frame. 
    /// </summary> 
    public sealed partial class MainPage : Page 
    { 
     public MainPage() 
     { 
      this.InitializeComponent(); 
     } 

     private void OnTermsAccepted(object sender, RoutedEventArgs e) 
     { 
      new MessageDialog(TermsText.Text).ShowAsync(); 
     } 
    } 
} 
+0

究竟如何我上面的XAML翻譯成風格/ Setter/Property格式? – 2013-03-02 23:58:01

+0

更新了答案 – 2013-03-03 05:37:30

+0

好吧,這一切似乎工作得很好。謝謝!最後一個問題,這到底是什麼呢? [TemplatePart(Name =「_OK」,Type = typeof(Button))] – 2013-03-03 18:31:27