Windows Phone:为什么这个Style没有应用于C#中的Button?

时间:2015-02-09 23:16:45

标签: c# wpf xaml windows-phone

我试图理解为什么没有将Style应用于C#中的Button控件。我找到了一种简单的方法来重现这个问题:在Visual Studio中关闭一个新的Windows Phone空白应用程序模板,将以下代码行添加到MainPage.xaml

<Page.Resources>
    <Style x:Name="TileStyle" TargetType="Button">
        <Setter Property="BorderThickness" Value="0,0,0,0" />
    </Style>
</Page.Resources>

<Button x:Name="btn" Style="{StaticResource TileStyle}" />

当应用程序运行时,Button是无边框的(应该是这样)。 然而,当您将此行代码添加到代码隐藏文件中的OnNavigatedTo事件处理程序时:

btn.Style = TileStyle;

当您运行应用程序时,该按钮不再是无边框的。这是为什么?

2 个答案:

答案 0 :(得分:1)

Windows Phone应用程序中存在一些资源和FindName方法的怪癖。在这种情况下,问题与OnNavigatedToLoaded或其他生命周期事件无关。

在深入研究这个问题之前,解决方案适用于所有情况。它直接使用ResourceDictionary

解决方法

// this will fail is some circumstances
btn.Style = TileStyle;

// this appears to work at any point in the 
// lifecycle, (assuming the style is in the Page.Resources element).
btn.Style = this.Resources["TileStyle"] as Style;

现在了解一些细节。这是我用来测试的一个简单的复制品。

<强> XAML

<Page.Resources>
  <!-- FirstButtonStyle is defined 
        and accessed with the StaticResource
        markup extension. -->
  <Style x:Name='FirstButtonStyle'
          TargetType='Button'>
    <Setter Property="BorderThickness"
            Value="0,0,0,0" />

  </Style>
  <!-- SecondButtonStyle is defined, 
        but not used -->
  <Style x:Name="SecondButtonStyle"
          TargetType="Button">
    <Setter Property="BorderThickness"
            Value="0,0,0,0" />
  </Style>


</Page.Resources>
  <StackPanel x:Name='MainPanel'>

    <Button x:Name="btn1"
            Style="{StaticResource FirstButtonStyle}"
            Content='Hello'
            Click='btn_Click' />
    <Button x:Name="btn2"
            Content='Hello'
            Click='btn_Click' />

  </StackPanel>

Windows Phone使用FindName方法中的InitializeComponent方法为每个命名元素设置变量。您可以在自动生成的文件中看到此代码(在我的情况下,该文件是位于obj文件夹中的NullStylePage.g.i.cs文件)。

我的XAML中有五个命名项。以下是InitializeComponent中自动生成的代码。

<强>代码

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent()
{
    if (_contentLoaded)
        return;

    _contentLoaded = true;
    global::Windows.UI.Xaml.Application.LoadComponent(this, 
            new global::System.Uri("ms-appx:///NullStylePage.xaml"), global::Windows.UI.Xaml.Controls.Primitives.ComponentResourceLocation.Application);

    FirstButtonStyle = (global::Windows.UI.Xaml.Style)this.FindName("FirstButtonStyle");
    SecondButtonStyle = (global::Windows.UI.Xaml.Style)this.FindName("SecondButtonStyle");
    MainPanel= (global::Windows.UI.Xaml.Controls.StackPanel)this.FindName("MainPanel");
    btn1 = (global::Windows.UI.Xaml.Controls.Button)this.FindName("btn1");
    btn2 = (global::Windows.UI.Xaml.Controls.Button)this.FindName("btn2");
}

在此方法的最后一行放置一个断点,您可以看到哪些项为null。由于InitializeComponent()方法标有DebuggerNonUserCodeAttribute,因此您需要关闭工具/选项中的启用我的代码选项以逐步执行代码调试器。

enter image description here

这是Watch Window的截图。

enter image description here

正如您所看到的,FirstButtonStyle的值为null。怪癖是这样的。如果样式未应用于元素(使用StaticResource),则会正确实例化变量。将样式应用于任何元素时,该变量为null

我不确定这是否是已知错误,但解决方法是使用Page.Resources中的样式。

 btn.Style = this.Resources["TileStyle"] as Style;

答案 1 :(得分:0)

我怀疑在OnNavigatedTo时页面还没有完全构建,因此分配不起作用。尝试将Loaded事件添加到页面,然后在那里执行赋值。