Windows Phone: 为什么这个样式没有应用到 C# 中的按钮?
Windows Phone: Why is this Style not being applied to the Button in C#?
我想了解为什么样式未应用于 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}" />
当应用程序 运行 时,按钮是无边框的(应该是这样)。 但是, 当您将这行代码添加到代码隐藏文件中的 OnNavigatedTo
事件处理程序时:
btn.Style = TileStyle;
当您 运行 应用程序时,按钮不再是无边框的。这是为什么?
我怀疑页面在 OnNavigatedTo 时尚未完全构建,因此分配无效。尝试向页面添加一个 Loaded 事件,然后在其中执行分配。
Windows Phone 应用程序中的资源和 FindName
方法存在一些问题。在这种情况下,问题与 OnNavigatedTo
、Loaded
或其他生命周期事件无关。
在深入研究问题之前,这里有一个适用于所有情况的解决方案。它直接使用 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");
}
在这个方法的最后一行打个断点,你可以看到哪些项目是空的。由于 InitializeComponent()
方法标有 DebuggerNonUserCodeAttribute
,因此您需要关闭 Tools/Options 中的 Enable Just My Code 选项以单步执行调试器中的代码。
这是手表的屏幕截图 Window。
如您所见,FirstButtonStyle
的值为空。怪癖是这样的。当样式未应用于元素(使用 StaticResource
)时,变量将被正确实例化。当样式应用于任何元素时,变量为 null
.
我不确定这是否是已知错误,但解决方法是使用 Page.Resources.
中的样式
btn.Style = this.Resources["TileStyle"] as 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}" />
当应用程序 运行 时,按钮是无边框的(应该是这样)。 但是, 当您将这行代码添加到代码隐藏文件中的 OnNavigatedTo
事件处理程序时:
btn.Style = TileStyle;
当您 运行 应用程序时,按钮不再是无边框的。这是为什么?
我怀疑页面在 OnNavigatedTo 时尚未完全构建,因此分配无效。尝试向页面添加一个 Loaded 事件,然后在其中执行分配。
Windows Phone 应用程序中的资源和 FindName
方法存在一些问题。在这种情况下,问题与 OnNavigatedTo
、Loaded
或其他生命周期事件无关。
在深入研究问题之前,这里有一个适用于所有情况的解决方案。它直接使用 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");
}
在这个方法的最后一行打个断点,你可以看到哪些项目是空的。由于 InitializeComponent()
方法标有 DebuggerNonUserCodeAttribute
,因此您需要关闭 Tools/Options 中的 Enable Just My Code 选项以单步执行调试器中的代码。
这是手表的屏幕截图 Window。
如您所见,FirstButtonStyle
的值为空。怪癖是这样的。当样式未应用于元素(使用 StaticResource
)时,变量将被正确实例化。当样式应用于任何元素时,变量为 null
.
我不确定这是否是已知错误,但解决方法是使用 Page.Resources.
中的样式 btn.Style = this.Resources["TileStyle"] as Style;