![](/img/trans.png)
[英]Windows Phone: Why is this Style not being applied to the Button in C#?
[英]Windows Phone: XAML Style 'resets' itself when applied in C#
編輯 :我已經找到了重現該問題的最小方法。 在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;
當您導航到頁面時,重現該問題。
原始文本:我正在嘗試創建Windows Phone應用程序,它是Whack-A-Mole的最低版本。 在游戲的頁面上,我有兩種用XAML編寫的按鈕樣式,它們表示一個孔被占用或未被占用。
<Page.Resources>
<Style x:Name="TileStyle" TargetType="Button">
<Setter Property="BorderThickness" Value="0,0,0,0" />
<Setter Property="Width" Value="125"/>
<Setter Property="Height" Value="125" />
</Style>
<Style x:Name="CircleStyle" TargetType="Button"
BasedOn="{StaticResource TileStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Background}" />
<Image Source="/Assets/white_circle.png" />
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<!--later on...-->
<Grid>
<Button Style="{StaticResource TileStyle}" Click="Button_Click"/>
<Button Style="{StaticResource TileStyle}" Click="Button_Click"/>
<Button Style="{StaticResource TileStyle}" Click="Button_Click"/>
...
</Grid>
第一種樣式實際上只是一個空白的黑色125x125正方形; 您只能通過單擊它來知道它在那里。 第二種樣式基於該樣式,並顯示white_circle.png代替空白正方形。
在我的代碼隱藏C#文件中,我有兩種利用這些樣式的方法:一種在Page加載時調用,另一種在單擊Button時調用。
protected async void OnNavigatedTo(NavigationEventArgs e)
while (!hasUserWonGame)
//sleeps for 1-3 secs
//decides where circle should go at by generating random int
b.Style = CircleStyle; //this works fine!
//more logic, waits
if (!hasUserWonRound)
b.Style = TileStyle; //reverts to TileStyle (this does not work!)
private void Button_Click(object sender, RoutedEventArgs e)
//decides if user is clicking on a circle
if (areTilesDisplayingCircle[index - 1])
//user has won the round!
hasUserWonRound = true;
b.Style = TileStyle; //this also does not work!
//more logic, updates score, decides if user has won the entire game
當用戶第一次導航到頁面時,按鈕全都是黑色的,因此應該是不可見的。 白色圓圈將按預期出現在空間中。 但是,當它從該點消失時,該圓會留在沒有應用樣式的Button后面。 (參見圖片。)
感謝您提供最少的復制情況。 這樣就很容易解釋發生了什么(嗯,至少在那種情況下……人們希望您的現實情況實際上是相似的,而且這確實有可能)。
問題源於您為樣式資源使用x:Name
而不是x:Key
。 在這種情況下,它不會按照您的想法或希望做。 特別是,盡管編譯器確實根據資源的指定x:Name
值創建了名為TileStyle
的字段,而XAML編譯器允許使用x:Name
代替x:Key
指定的適當鍵, TileStyle
兩個不要連接。
編譯器生成的用於檢索TileStyle
字段的值的代碼使用與資源字典不兼容的機制,即,它將調用FindName()
方法,並傳遞您提供的名稱。 但是該方法用於在FrameworkElement
的對象圖中查找已命名的對象。 它不會(也不打算)在資源字典中查找對象。
基本上,編譯器看到x:Name
並愉快地發出其樣板,以實現支持元素的字段。 它只是盲目地遵循實現x:Name
的規則,事實證明這不適用於資源。
那么,當您調用FindName()
並傳遞不存在的名稱時會發生什么呢? 返回null
。 因此, TileStyle
字段獲得(或保持TileStyle
,因為這是默認值)的null
。
當將Button
對象的Style
屬性設置為null
時會發生什么? 它只是將所有內容重置為默認值! 由於{StaticResource TileStyle}
語法是處理資源的正確語法,並且允許使用x:Name
替代資源x:Key
屬性,因此Button
最初看起來不錯(在您的實際情況下)。
在最小的復制示例中,最直接的解決方法是正確初始化資源(使用x:Name
語法用於特定的基於Storyboard
的場景,通常不是正確的實現方式),然后顯式地進行初始化。實現您的TileStyle
字段:
<Page.Resources>
<Style x:Key="TileStyle" TargetType="Button">
<Setter Property="BorderThickness" Value="0,0,0,0" />
</Style>
</Page.Resources>
然后在您的代碼背后:
partial class MainPage : Page
{
private Style TileStyle;
public MainPage()
{
InitializeComponent();
TileStyle = (Style)this.Resources["TileStyle"];
// etc.
}
}
這樣,您現在應該為樣式字段提供非null值,並且將它們分配給Style
屬性應該正確更新樣式,而不是將其重置。
就是說,我不清楚,雖然以上內容顯然是針對您的最小再現案例的解決方案,但它是否適用於您的實際情況。 特別是,在您的問題中,您聲稱將CircleStyle
的值分配給Button
的Style
屬性確實有效。 但是,假設CircleStyle
字段的初始化方式與TileStyle
字段相同,則不清楚為什么在分配TileStyle
不會TileStyle
。
也就是說,我希望CircleStyle
字段也為null
,但是如果分配確實將樣式更改為您想要的樣式,則顯然不能為null
。 如果它不為null
,那么為什么TileStyle
為null
? 但是,如果沒有一個很好的,最小的,完整的代碼示例來精確解決該問題,我將無法回答任何有關此的問題。
最后,我將指出,這樣做可能比在后面的代碼中硬編碼樣式更好。 不幸的是,我對Phone API不夠熟悉,無法知道可能是什么。
在WPF中,我將使用StyleSelector
或Trigger
基於基礎模型對象中的某些綁定屬性來更改對象外觀。 但是經過大量的時間試驗后,我發現我對Phone API的了解還不夠多,無法知道它們將如何工作。 在Style.Triggers
集合中似乎甚至不支持Trigger
類,或者至少不允許使用該Trigger
類,並且我最終掉下了兔子洞,試圖弄清楚如何在Phone中使用基於Grid
的ItemsControl
(在WPF中)這並不難,但是綁定到Grid.Row
和Grid.Column
附加屬性有一些技巧,這些屬性在Phone中不起作用,因為顯然Phone不支持在樣式的Setter
的Value
屬性中使用Binding
。
基本上,有一噸從Silverlight的/電話/ WinRT的實施基於XAML的API的缺失,相比WPF。 我以前使用WPF的經驗並不能幫助我解決上述問題,因為我在WPF中依賴於實現這些行為的很多功能只是其他API中不存在(對Microsoft感到羞恥!)。
同時,我希望上述基於代碼隱藏的方法能夠解決您的特定問題。 如果沒有,那么您將需要發布一個更好的示例,但是仍然是最少和完整的代碼示例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.